04-21-2015 07:15 AM
Hi,
I've encounterd an issue which I'm trying to end a thread from another thread
I have one main thread that calls two different threads (Thread1 & Thread2) as so:
Thread1() { ... while (g_ThLoop) { ...Do stuff... } ...Cleanning memory etc.... } Thread2() { g_ThLoop = 0; } MainThread() { .... g_ThLoop = 1; CmtScheduleThreadPoolFunction (DEFAULT_THREAD_POOL_HANDLE, Thread1, 0, &hFid1); ....Do Stuff... CmtScheduleThreadPoolFunction (DEFAULT_THREAD_POOL_HANDLE, Thread2, 0, &hFid2); CmtWaitForThreadPoolFunctionCompletion (DEFAULT_THREAD_POOL_HANDLE, hFid1, 0); CmtWaitForThreadPoolFunctionCompletion (DEFAULT_THREAD_POOL_HANDLE, hFid2, 0); CmtReleaseThreadPoolFunctionID (DEFAULT_THREAD_POOL_HANDLE, hFid1); CmtReleaseThreadPoolFunctionID (DEFAULT_THREAD_POOL_HANDLE, hFid2); }
I've tried to debug in debug and release configuration but the change of g_ThLoop from Thread2 doesn't make Thread1 to exit
also tried to use CmtLock, Local Variable and Safe Variable but...with no success 😞
Uriya
04-21-2015 08:19 AM - edited 04-21-2015 08:23 AM
How is your g_ThLoop variable defined?
In Monitoring and Controlling Secondary Threads help topic the following note can be found:
Note If you use the volatile keyword, this code will function properly in an optimizing compiler such as Microsoft Visual C++. An optimizing compiler determines that nothing inside the while loop can change the value of the quit variable. Therefore, as an optimization, the compiler might use only the initial value of the quit variable in the whileloop condition. Use the volatile keyword to notify the compiler that another thread might change the value of the quit variable. As a result, the compiler uses the updated value of the quit variable each time the loop executes.
Multitthreading is indeed a powerful technique but requires a non trivial knowledge of its inner aspects. I suggest you to carefully read Creating Multithreaded Applications topic in the CVI help: it gives the basics of multithreading and a lot of advanced features you should know to master this technique.
04-26-2015 11:54 AM
Thanks RobertoBozzolo for your quick reply,
you're right, I've forgot to write down the g_ThLoop declaration.
g_ThLoop is declared on top, using volatile like this:
volatile int g_ThLoop;
I also tried to not use volatile and just using only int instaed, but with no success...
I have new info:
When I try to debug my program, I always come across that Thread1 is frozen which means that it doesnt do any IO and in the Threads monitor, it look grayed out (dimmed) so I think it got on a suspended mode or something like that.
Im not ruling out the possibility that the g_ThLoop doesnt change at all but it seems to me that it's not involved.
Uriya
04-26-2015 12:50 PM
It may seems a silly comment, but have you tried to step into the thread function to understand whether it exits prematurely from the loop due to unpredictable conditions?
04-29-2015 06:58 AM
From what I've learned in the life of the simple programmer - there is no silly comments 🙂
Actually I've checked if the thread exiting prematurely by putting a break point after its loop clause but nothing happend 😕 and whene I open Threads window (on CVI IDE) I can see it still 'alive'.
That why I think the thread went frozen..but maybe there is a better way to check if the thread is exiting or not...but that what i know about thread debugging...
so....no luck so far.....
04-29-2015 08:38 AM
Can you reduce your project to a minimum that exposes only the behaviour we are discussing about?
Examining some real code may lead to some new idea to solve the problem.
04-30-2015 05:11 AM
Hi,
The (g_ThLoop) check cannot be done until "Do stuff" is done. So if it takes too much time or if it is stuck inside, the thread1 function is not terminated.
Checking this by debuger may be useful. Do you know that you can switch the the debuger view in "Threads window"?, just double click on thread.
But do not be confused that the thread is not automaticaly closed when your Thread function is done. The thread remains in thread pool until application exit(so threads can be reused if need).
Also using some flag variables to check the state of thread1 may be useful (for example, does the thread1 start?, Does the thread1 reach the start of while cykle?,Number of iteration throught while cykle,...)
From other perspective, If you have multicore/multiprocesor system, the "volatile" keyword is maybe not enought. Specialy if you enable agresive optimization the problem can be worse.
In your case, it is not very likely the problem (because this is very simple logic, and windows swap threads between processors,..) but for more safety please use standard synchronization primitives from existing library library.
In this case:
while (__sync_fetch_and_add(&g_Thread,0)==0) //while (g_Thread==0)
__sync_fetch_and_add(&g_thread,1) //g_thread=1;
You can also use InterlockedCompareExchange and InterlockedIncrement functions.
I hope this help.
P.S. i am sorry for my bad english