alberthyc


hi, i wrote a mfc dialog that's running a worker thread i want to terminate it from outside.

in CMyTestDlg: public CDialog{
static bool STOP;//a shared variable to signal the thread function
static UINT __cdecl Start();
CWinThread* pThread
....
in the cpp file, i have a OnBnClickedButtonStart() and OnBnClickedButtonStop()function to start and stop the thread
bool CMyTestDlg:: Stop=false;

void CMyTestDlg:: OnBnClickedButtonStart(){
pThread=AfxBeginThread(Start,this,-1,0,CREATE_SUSPENDED);
pThread->m_bAutoDelete=FALSE;
pThread->ResumeThread();
}

void CMyTestDlg:: OnBnClickedButtonStop()
{
STOP=true;
if(:: WaitForSingleObject(pThread->m_hThread,2000)==WAIT_OBJECT_0){
delete pThread;
m_ListBox_MSG.AddString(_T("Thread terminated succesfully"));
//message showed in a list box
}
else{
:: TerminateThread(pThread->m_hThread,0);
m_ListBox_MSG.AddString(_T("Thread is not normally terminated!"));
//message showed in a list box
}
}

UINT __cdecl CMyTestDlg:: Start(LPVOID pParam){

CMyTestDlg* me=(CMyTestDlg*)pParam;
while(STOP==false){
//looping here...

}
return 0;
}



when i stop the thread, from the message showed in the listbox, i found that the thread is always terminated "dangeroursly" which means the ::TerminateThread()function ran.

What could be the possible cause



Re: having problem terminating a thread

crescens2k


The thread is taking longer than you think to shut down or it is not trying to shut down. You should look into your worker thread and see how long it takes to shut down.






Re: having problem terminating a thread

rtpninja

Without going into details as to why, I suggest you don't use WaitForSingleObject() on the thread handle.

Instead, create an "shutdown" event with the CreateEvent API or CEvent and use WaitForSingleObject() on that.

The UI thread creates the event and waits on it.

The worker thread sets the event to signalled when it terminates.

This achieves the same thing you're trying to do, but bypasses some timing issues.






Re: having problem terminating a thread

Holger Grund

Depending on what you do exactly in the while loop body, the compiler may just optimize the read of STOP (I suppose it's the same as the static data member "Stop"). You should really mark it at least as volatile. In fact, I still happen to think that a memory barrier is required here -- but that has been discussed at length in another thread.

Of course, you can simply take a look at the generated assembly code. In debug mode everything should work as expected.

-hg





Re: having problem terminating a thread

Simple Samples

Instead of bool STOP use an event, as in CEvent. I don't know if that will fix the problem but it is definitely a mistake to use a bool for inter-thread synchronization.






Re: having problem terminating a thread

Simple Samples

rtpninja wrote:
Without going into details as to why, I suggest you don't use WaitForSingleObject() on the thread handle.

Please do explain why it is a mistake to wait on the thread handle.

I agree that an event is needed; at least one event, but I think there would be timing issues if the thread handle is not used for synchronizing with the successful completion of the thread.






Re: having problem terminating a thread

Holger Grund

Simple Samples wrote:

Instead of bool STOP use an event, as in CEvent. I don't know if that will fix the problem but it is definitely a mistake to use a bool for inter-thread synchronization.

What makes you believe that This has been used for ages and works just fine. Polling an event really doesn't make any sense.

The OP's code should work just fine assuming 2000 is large enough for normal thread cleanup and that correct handling of state shared across threads is ensured. It's definitely not a mistake to use a bool to communicate status across threads so long as memory coherence rules are followed.

-hg





Re: having problem terminating a thread

Simple Samples

Your code works for me.






Re: having problem terminating a thread

alberthyc

thx for the replies, using the while loop and and boolean variable is quite common, i really don't see any problem with this method.

some modification of the code for the thread function,

UINT __cdecl CMyTestDlg:: Start(LPVOID pParam){

CMyTestDlg*me=(CMyTestDlg*)pParam;

while(STOP==false){

//looping here....

...}

me->m_ListBox_Msg.AddString(_T("Thread Ended"));//add a message to the list box

return0;

}

when i try to end the thread, this "Thread Ended" msg never showed up, it means the loop didn't exit, what could be wrong





Re: having problem terminating a thread

Simple Samples

Sorry, when I tested your code, I did not use the listbox. When I used the listbox I got the same results you did. I see many times comments saying not to use a window created in another thread. Did you look for previous answers If you did, I think you would have seen comments to not use windows belonging to another thread. So use something else to debug, such as TRACE macros or a file you create for debugging. Or if you need the listbox for more than diagnostic purposes, use something that allows your worker thread to safely communicate with the main thread.






Re: having problem terminating a thread

alberthyc

hi, thx for the reply, i guess i need to explain my situation more clearly.

i have a mfc dialog which have several slider controls, i have a function that reads the slider postion and store into a data array or buffers. the data stored in the array will be outputed from hardware using FIFO mode. I want this output to be continous and can be changed real time, which means by chaning the slider control position, the data output is changed.

UINT Start(LPVOID pParam){


CMyTestDlg*me=(CMyTestDlg*)pParam;

while(Stop==false){

me->Getdata(me);//accessing the UI slider control here;

me->Outputdata();

}

...

return 0;

}

so as you can see, i have to access the slider control in my worker thread, any suggestions





Re: having problem terminating a thread

alberthyc

just wrote a simpyfied version, i think it's definitely the problem of accessing UI controls.

void CMultiTheadingTestDlg:: OnBnClickedButtonStart()
{
// TODO: Add your control notification handler code here
Stop_MyWorkerThread=false;
pThread = :: AfxBeginThread( Start, this, 0, 0, CREATE_SUSPENDED);
pThread->m_bAutoDelete = FALSE;
pThread->ResumeThread();

}

void CMultiTheadingTestDlg:: OnBnClickedButtonStop()
{
// TODO: Add your control notification handler code here
Stop_MyWorkerThread=true;
if(:: WaitForSingleObject(pThread->m_hThread,INFINITE))
delete pThread;
}

UINT __cdecl CMultiTheadingTestDlg:: Start(LPVOID pParam)

{

CMultiTheadingTestDlg*me=(CMultiTheadingTestDlg*)pParam;
me->count=0;
while(me->Stop_MyWorkerThread==false){
me->OutputData(me);
me->count++;
}

return 0;
}

void CMultiTheadingTestDlg:: OutputData(CMultiTheadingTestDlg*pParam){
for(int i=0;i<2;i++)
pParam->Array[i ]=pParam->m_SliderCtrl_Data[i ].GetPos();
}

i try try using the CEvent, not sure if that helps




Re: having problem terminating a thread

Simple Samples

Simple Samples wrote:
use something that allows your worker thread to safely communicate with the main thread.

alberthyc wrote:
so as you can see, i have to access the slider control in my worker thread, any suggestions

I already provided a suggestion. You probably need an event or two for the threads to communicate. Also create something such as a string or a stack of strings or a class or whatever you need to hold the necessary data. Then the worker thread can get data from and/or put data to the main thread with the window (slider control). Then the main thread will do everything that is done directly to the window. The worker thread can still do whatever it needs but it simply does not interface with the window directly.






Re: having problem terminating a thread

Simple Samples

alberthyc wrote:
i try try using the CEvent, not sure if that helps

I am nearly sure that won't help the problem you are asking about. I am still not sure whether an event has no advantage, but it is not likely to have any advantage in this situation.






Re: having problem terminating a thread

alberthyc

so instead of running the OutputData() in the thread it self, the thread should send some kind of event or notification message to the main thread and main thread run the Outputdata() which get the data and stores it, after finish it, sends another notification to the thread and keep this kind thing running.

Is this achievable






databaseforum