05-10-2009 10:31 AM
Hi,
when shutting down a multithreaded application, the main thread schedules functions that will terminate the secondary threads, using PostDeferredCallToThread ( callback_function, callback_data, thread_id ) in a loop over all seconadry threads.
This works fine, and I can close the application as intended.
However, if I add another line to the loop, as recommended by the NI sample programs, CmtWaitForThreadPoolFunctionCompletion ( pool_handle, thread_function_id, OPT_TP_PROCESS_EVENTS_WHILE_WAITING ),
I receive an error message:
The function ID you passed is owned by the thread pool. This operation can only be performed on a function ID that you own.
This loop is initiated by the main thread, so how can the thread pool own a function ID?
I am using the pool handle that I obtained from the CmtNewThreadPool and not the default thread pool handle.
Thanks (and no more posts today)
Wolfgang
05-10-2009 07:06 PM - edited 05-10-2009 07:07 PM
Hi Wolfgang.
Keep in mind that callback_function you specify in the CmtWaitForThreadPoolFunctionCompletion() call will not execute until the thread becomes idle, so thread_function_id will not be valid.
Here is a simple approach that works for me:
int Shutdown; // global variable
int myThreadPool;
int main (int argc, char *argv[])
{
Shutdown = 0;
CmtNewThreadPool(nThreads, &myThreadPool);
...
// Signal threads - application is closing
Shutdown = 1;
CmtDiscardThreadPool(myThreadPool); // Blocks until all threads in thread pool are idle
return 0;
}
Each thread function (including those running in the default thread pool) includes lines similar to:
while(!Shutdown && someOtherCondition)
ProcessSystemEvents();
return 0;
Colin.
05-11-2009 03:37 AM
Hi Colin,
sounds reasonable, but still this answer is confusing me because...
Recently, I have obtained a nice sample code from Roberto (here http://forums.ni.com/ni/board/message?board.id=180&message.id=41004#M41004)
which does exactly (?!) the same thing:
PostDeferredCallToThread (QuitUICallback, 0, threadID);
CmtWaitForThreadPoolFunctionCompletion (poolHandle, fnID, OPT_TP_PROCESS_EVENTS_WHILE_WAITING);
and it worked just fine...
Wolfgang
05-11-2009 06:08 AM
Hello Wolfgang.
My apologies. When you wrote "...the main thread schedules functions..." I assumed that you were calling CmtScheduleThreadPoolFunction() or CmtScheduleThreadPoolFunctionAdv() - I ignored "...using PostDeferredCallToThread()...".
I looked at the modified MultiPanel sample provided by Roberto. If your code is similar in structure, I can see no reason why it should not work as you expect.
Does your code include any calls to CmtReleaseThreadPoolFunctionID()? I imagine that if you call CmtWaitForThreadPoolFunctionCompletion() after the function ID has been released, you will generate an error.
Good luck.
Colin.
05-11-2009 07:31 AM
Hi Colin,
Thanks for suggesting to check for CmtReleaseThreadPoolFunctionID. Indeed I had such a call, but even if commenting it out the error remains the same. By the way, when calling CmtReleaseThreadPoolFunctionID instead of CmtWaitForThreadPoolFunctionCompletion, I receive the same error...?? This seems to suggest that something with my pool handle is wrong, but I make use of it only once, when starting the secondary threads from the primay threads using
CmtScheduleThreadPoolFunctionAdv ( pool_handle, thread_function, thread_function_data, csi_process_class, callback_function,
( EVENT_TP_THREAD_FUNCTION_BEGIN || EVENT_TP_THREAD_FUNCTION_END ), 0, RUN_IN_SCHEDULED_THREAD, NULL )
I can't see anything wrong here...
Wolfgang