How to terminate the secondary thread when the application closed?
-
Hallo, I have an application that uses a secondary thread to excute a very long function, what i need is, how to terminate the secondary thread "CLEANLY" if the main appliction is going to be closed while the seconndary thread is still excuting the verx long function? i started with : ON_WM_Close() in the View.cpp file, but i do not know how to continue: The secondary thread should become a Message if the the x or End in the Main application werde clicked. Please help(with code).
-
Hallo, I have an application that uses a secondary thread to excute a very long function, what i need is, how to terminate the secondary thread "CLEANLY" if the main appliction is going to be closed while the seconndary thread is still excuting the verx long function? i started with : ON_WM_Close() in the View.cpp file, but i do not know how to continue: The secondary thread should become a Message if the the x or End in the Main application werde clicked. Please help(with code).
The secondary thread can execute its code within a spin loop, which can wait for an event to "happen" (with a wait time of 0 ms). While you want to close your application, just set that particular event so that the secondary thread would have a chance to clean itself up properly. You could similarly use another event (with a timeout) that the secondary thread would "set" to inform the main thread that it has finished cleaning up and is on its way to terminate. Take a look at WaitForSingleObject[^]. Attempt it, and if you get stuck somewhere, or if you don't understand any of it, post it here (with relevant source code, if any). MTRecalc[^] sample makes use of events, which you can refer to.
It is a crappy thing, but it's life -^ Carlo Pallini
-
The secondary thread can execute its code within a spin loop, which can wait for an event to "happen" (with a wait time of 0 ms). While you want to close your application, just set that particular event so that the secondary thread would have a chance to clean itself up properly. You could similarly use another event (with a timeout) that the secondary thread would "set" to inform the main thread that it has finished cleaning up and is on its way to terminate. Take a look at WaitForSingleObject[^]. Attempt it, and if you get stuck somewhere, or if you don't understand any of it, post it here (with relevant source code, if any). MTRecalc[^] sample makes use of events, which you can refer to.
It is a crappy thing, but it's life -^ Carlo Pallini
bool PrintMy Results(const CString& strMyResult) { bool bTerminate = false; while(!bTerminate && nCount < arrMyResults.GetSize()) { if (::WaitForSingleObject(m_End_Event.m_hObject, 0) == WAIT_OBJECT_0) { bTerminate = true; continue; } nCount++; // Code to print the Array-Elements // I am hier inside the secondary thread wich is in another // class as the Doc class, how can I till him hier that the //application is going to be finsihed and he must finsh the printing //of the last line of the Array? } }
-
bool PrintMy Results(const CString& strMyResult) { bool bTerminate = false; while(!bTerminate && nCount < arrMyResults.GetSize()) { if (::WaitForSingleObject(m_End_Event.m_hObject, 0) == WAIT_OBJECT_0) { bTerminate = true; continue; } nCount++; // Code to print the Array-Elements // I am hier inside the secondary thread wich is in another // class as the Doc class, how can I till him hier that the //application is going to be finsihed and he must finsh the printing //of the last line of the Array? } }
WARNING: I don't have VS on this machine, I've typed the code out manually and I've no way to compile it. I've verified whatever I can, but please make sure that it works fine before you use it. Use it at your own risk, keep out of reach of children, do not expose to sunlight, etc., Global handle variables to store the event:
HANDLE hDieNow, hImDead; //Global variables
Function where you'd create the events (preferably InitDialog or something like that):
CMyDialog::OnInitDialog()
{
//other stuff//create the events here
hDieNow = CreateEvent(NULL, TRUE, FALSE, NULL);
hImDead = CreateEvent(NULL, TRUE, FALSE, NULL);//Please look into the documentation of CreateEvent to know about the parameters.
return TRUE;
}Thread function:
UINT ThreadFunc(LPVOID pFuncParams)
{
while(true)
{
if(WaitForSingleObject(hDieNow, 0) == WAIT_OBJECT_0)
break;else
{
//Your thread code should be here.
Sleep(100);
OutputDebugString(_T("Thread probe...\n"));
}
}
SetEvent(hImDead); //Tell the main thread that clean up is complete.
return false;
}Application close handler function:
CMyDialog::OnClose()
{
SetEvent(hDieNow); //Tell the thread to stop everything and do clean up.
DWORD dwResult = WaitForSingleObject(hImDead, 5000); //Give the thread 5 seconds to clean up.
//Check the value of dwResult. It must be WAIT_OBJECT_0, if the wait succeeded!//Proceed to quit the application. The thread must be dead now.
}It is a crappy thing, but it's life -^ Carlo Pallini
-
WARNING: I don't have VS on this machine, I've typed the code out manually and I've no way to compile it. I've verified whatever I can, but please make sure that it works fine before you use it. Use it at your own risk, keep out of reach of children, do not expose to sunlight, etc., Global handle variables to store the event:
HANDLE hDieNow, hImDead; //Global variables
Function where you'd create the events (preferably InitDialog or something like that):
CMyDialog::OnInitDialog()
{
//other stuff//create the events here
hDieNow = CreateEvent(NULL, TRUE, FALSE, NULL);
hImDead = CreateEvent(NULL, TRUE, FALSE, NULL);//Please look into the documentation of CreateEvent to know about the parameters.
return TRUE;
}Thread function:
UINT ThreadFunc(LPVOID pFuncParams)
{
while(true)
{
if(WaitForSingleObject(hDieNow, 0) == WAIT_OBJECT_0)
break;else
{
//Your thread code should be here.
Sleep(100);
OutputDebugString(_T("Thread probe...\n"));
}
}
SetEvent(hImDead); //Tell the main thread that clean up is complete.
return false;
}Application close handler function:
CMyDialog::OnClose()
{
SetEvent(hDieNow); //Tell the thread to stop everything and do clean up.
DWORD dwResult = WaitForSingleObject(hImDead, 5000); //Give the thread 5 seconds to clean up.
//Check the value of dwResult. It must be WAIT_OBJECT_0, if the wait succeeded!//Proceed to quit the application. The thread must be dead now.
}It is a crappy thing, but it's life -^ Carlo Pallini
-
thanks. I am using SDI application, so i will put the code in BOOL OnNewDocument() instead of OnInitDialg(). Now a general question: why can i not use ON_WM_CLOSE() to tell the small thread to terminate himself and if yes how? Thanks a lot
susanne1 wrote:
I am using SDI application, so i will put the code in BOOL OnNewDocument() instead of OnInitDialg().
Do it wherever. You just need to create those events, before you would use it. But be sure on that, or the WaitFor... call is going to fail and you'll not get desired results.
susanne1 wrote:
Now a general question: why can i not use ON_WM_CLOSE() to tell the small thread to terminate himself and if yes how?
What do you mean how? I just demonstrated that to you with an example in my previous post. Just set the event that the worker thread is spinning on (waiting to be set) and then wait for the worker thread to set the "I'm dead" event (which is kind of an acknowledgment from the thread that the cleanup is complete).
It is a crappy thing, but it's life -^ Carlo Pallini
-
Hallo, I have an application that uses a secondary thread to excute a very long function, what i need is, how to terminate the secondary thread "CLEANLY" if the main appliction is going to be closed while the seconndary thread is still excuting the verx long function? i started with : ON_WM_Close() in the View.cpp file, but i do not know how to continue: The secondary thread should become a Message if the the x or End in the Main application werde clicked. Please help(with code).
When asked to close, the primary thread needs to signal an event that the secondary thread is monitoring. Once signaled, the primary thread would then wait for the secondary thread to finish. This is very easy to do with two
CEvent
objects. [edit] I now see that Rajesh has an excellent example. [/edit]"Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
-
bool PrintMy Results(const CString& strMyResult) { bool bTerminate = false; while(!bTerminate && nCount < arrMyResults.GetSize()) { if (::WaitForSingleObject(m_End_Event.m_hObject, 0) == WAIT_OBJECT_0) { bTerminate = true; continue; } nCount++; // Code to print the Array-Elements // I am hier inside the secondary thread wich is in another // class as the Doc class, how can I till him hier that the //application is going to be finsihed and he must finsh the printing //of the last line of the Array? } }
As you've shown this code, here's a potential solution:
-
Ensure there is a
volatile LONG
variable (let's call it lTerminate) visible to both your main thread's code and your second thread's code. Initialise that variable to 0 before the second thread is started -
When you start the second thread, store its handle somewhere it can be seen by the code that will terminate the thread.
-
The second thread's loop should look like this:
bool PrintMy Results(const CString& strMyResult)
{
while(!lTerminate && nCount < arrMyResults.GetSize())
{
nCount++;
// Code to print the Array-Elements
// I am hier inside the secondary thread wich is in another // class as the Doc class, how can I till him hier that the //application is going to be finsihed and he must finsh the printing //of the last line of the Array?
}
} -
When you want to exit, set lTerminate to 1 with an appropriate function (as I'll show you below) and wait for the thread's handle to be set, as that indicates the thread has exitted:
::InterlockedExchange(&lTerminate, 1);
::WaitForSingleObject(hSecondThread, INFINITE);
Easy as...
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
-
-
As you've shown this code, here's a potential solution:
-
Ensure there is a
volatile LONG
variable (let's call it lTerminate) visible to both your main thread's code and your second thread's code. Initialise that variable to 0 before the second thread is started -
When you start the second thread, store its handle somewhere it can be seen by the code that will terminate the thread.
-
The second thread's loop should look like this:
bool PrintMy Results(const CString& strMyResult)
{
while(!lTerminate && nCount < arrMyResults.GetSize())
{
nCount++;
// Code to print the Array-Elements
// I am hier inside the secondary thread wich is in another // class as the Doc class, how can I till him hier that the //application is going to be finsihed and he must finsh the printing //of the last line of the Array?
}
} -
When you want to exit, set lTerminate to 1 with an appropriate function (as I'll show you below) and wait for the thread's handle to be set, as that indicates the thread has exitted:
::InterlockedExchange(&lTerminate, 1);
::WaitForSingleObject(hSecondThread, INFINITE);
Easy as...
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
Sweet! Have my vote, sir. :)
It is a crappy thing, but it's life -^ Carlo Pallini
-