-
May 22nd, 2012, 05:43 PM
#1
Stop a Thread
How do I stop a thread? I'm using ::TerminateThread within this code and the thread keeps running. Is this the correct procedure? Thanks for any help.
Code:
void CPageTwo::OnBnClickedButTest()
{
// Click First to Start Thread
// Click Again to End Thread
if(!m_pThread) // Start Thread
{
m_pThread = AfxBeginThread(ThreadFunc, this);
if(!m_pThread)
{
// Could not create thread
return;
}
}
else // End the thread
{
::TerminateThread( m_pThread, 0 );
m_pThread = 0;
}
}
UINT CPageTwo::ThreadFunc(LPVOID lpParam)
{
CPageTwo* p2 = (CPageTwo*)lpParam;
for(int i = 0; i < 100; ++i)
{
p2->PostMessage(WM_UPDATE_PROGRESS, 0, (LPARAM)i);
Sleep(2000);
}
return 0;
}
-
May 22nd, 2012, 08:14 PM
#2
Re: Stop a Thread
Originally Posted by cbpetro
How do I stop a thread? I'm using ::TerminateThread ...
Don't use TerminateThread. From the documentation at http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx :
Originally Posted by MSDN
TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems: [list of really bad things omitted -- go look at the link]
Do you have an "extreme case" that justifies the use of this "dangerous function"? Of course you don't.
In answer to your question of "how do I stop a thread", it's the thread itself that should monitor something that tells it to stop, and then the thread should simply exit from its THREADFUNC. For example, assuming that your class will create at most one thread, modifying your code gives the following:
Code:
void CPageTwo::OnBnClickedButTest()
{
// Click First to Start Thread
// Click Again to End Thread
if(!m_pThread) // Start Thread
{
m_bStop = FALSE; // this is a BOOL member variable
m_pThread = AfxBeginThread(ThreadFunc, this);
if(!m_pThread)
{
// Could not create thread
return;
}
}
else // End the thread
{
// ::TerminateThread( m_pThread, 0 );
m_bStop = TRUE;
m_pThread = 0;
}
}
UINT CPageTwo::ThreadFunc(LPVOID lpParam)
{
CPageTwo* p2 = (CPageTwo*)lpParam;
for(int i = 0; i < 100; ++i)
{
p2->PostMessage(WM_UPDATE_PROGRESS, 0, (LPARAM)i);
Sleep(2000);
if (p2->m_bStop)
break;
}
return 0;
}
Note that this is very rudimentary and relies on a few assumptions (such as atomicity of the change of m_bStop to TRUE, only one single thread since otherwise they would all be stopped, etc.) There are better and more robust methods, but in the end the principle is the same: tell the thread it's time to stop and then let the thread terminate itself by exiting from the THREADFUNC.
Mike
PS: Your code probably doesn't work because the thread handle doesn't have the THREAD_TERMINATE access right. See the docs. But you would learn a lot if you called GetLastError after the TerminateThread function fails.
-
May 22nd, 2012, 10:07 PM
#3
Re: Stop a Thread
Originally Posted by MikeAThon
There are better and more robust methods, but in the end the principle is the same: tell the thread it's time to stop and then let the thread terminate itself by exiting from the THREADFUNC.
Mike
Mike,
Thanks for your help, I'm starting to understand. I have one follow up question that maybe you or someone else can help with. I used AfxEndThread in the ThreadFunc because MSDN recommends this for cleanup.
My question is, Is there a way for calling function to get the status of the thread when it's completed, or stopped. I can do this by setting m_pThread = 0, but this does'nt seem proper if m_pThread is a pointer.
Code:
void CPageTwo::OnBnClickedButTest()
{
// Click First to Start Thread
// Click Again to End Thread
if(!m_pThread) // Start Thread
{
m_bStop = FALSE; // this is a BOOL member variable
m_pThread = AfxBeginThread(ThreadFunc, this);
if(!m_pThread)
{
// Could not create thread
return;
}
}
else // End the thread
{
m_bStop = TRUE;
m_pThread = 0;
}
}
UINT CPageTwo::ThreadFunc(LPVOID lpParam)
{
CPageTwo* p2 = (CPageTwo*)lpParam;
for(int i = 0; i < 5; ++i)
{
if (p2->m_bStop)
AfxEndThread(0, TRUE); //EXIT CODE = ?, DELETE THREAD = TRUE
p2->PostMessage(WM_UPDATE_PROGRESS, 0, (LPARAM)i);
Sleep(1000);
}
p2->m_bStop = FALSE; //
p2->m_pThread = 0; // Set the thread to O to let calling funtion know it's done - Ugly
AfxEndThread(0, TRUE); // EXIT CODE = ?, DELETE THREAD = TRUE
return 0;
}
-
May 23rd, 2012, 01:36 AM
#4
Re: Stop a Thread
This is all explained in MSDN:
http://msdn.microsoft.com/en-us/libr...=vs.80%29.aspx
Remarks
Must be called from within the thread to be terminated.
For more information on AfxEndThread, see the article Multithreading: Terminating Threads.
http://msdn.microsoft.com/en-us/libr...=vs.80%29.aspx
Regards,
Paul McKenzie
-
May 23rd, 2012, 03:16 AM
#5
Re: Stop a Thread
Originally Posted by cbpetro
... I used AfxEndThread in the ThreadFunc because MSDN recommends this for cleanup.
You should not. Just return any UINT number (so called "error code") from within the thread procedure. MFC framework will then call AfxEndThread exactly where and when it is needed!
Victor Nijegorodov
-
May 23rd, 2012, 03:28 AM
#6
Re: Stop a Thread
Cheers, D Drmmr
Please put [code][/code] tags around your code to preserve indentation and make it more readable.
As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky
-
May 23rd, 2012, 04:43 PM
#7
Re: Stop a Thread
Originally Posted by cbpetro
... My question is, Is there a way for calling function to get the status of the thread when it's completed, or stopped.
What do you mean by "calling function"? And what do you mean by "status" of a thread that's already completed? To me, the status of a thread that's completed is self-evidently "completed".
Have the others here answered your other questions?
-
May 23rd, 2012, 11:24 PM
#8
Re: Stop a Thread
GetExitCodeThread
Remarks
This function returns immediately. If the specified thread has not terminated and the function succeeds, the status returned is STILL_ACTIVE. If the thread has terminated and the function succeeds, the status returned is one of the following values:
- The exit value specified in the ExitThread or TerminateThread function.
- The return value from the thread function.
- The exit value of the thread's process.
Last edited by Igor Vartanov; May 23rd, 2012 at 11:28 PM.
Best regards,
Igor
-
May 24th, 2012, 01:31 AM
#9
Re: Stop a Thread
Originally Posted by MikeAThon
What do you mean by "calling function"? And what do you mean by "status" of a thread that's already completed? To me, the status of a thread that's completed is self-evidently "completed".
Have the others here answered your other questions?
Mike,
When you use the boolean to stop the thread, the thread is only stopped. The m_pThread is still a pointer to CWinThread. It seems to me, there may be three conditions you may want to account for...
1.) The thread is stopped and the user wants to RESTART the thread.
2.) The thread is stopped and the user wants to RESUME the thread.
3.) The thread was allowed to run and is completed.
Code:
// I refer to this as the "calling function"
void CPageTwo::OnBnClickedButTest()
{
// Click First to Start Thread
// Click Again to End Thread
if(!m_pThread) // Start Thread - My problem is here. Can I check if thread is completed? or is stopped?
{
m_bStop = FALSE; // this is a BOOL member variable
m_pThread = AfxBeginThread(ThreadFunc, this);
if(!m_pThread)
{
// Could not create thread
return;
}
}
else // End the thread
{
m_bStop = TRUE;
m_pThread = 0;
}
}
MSDN is kinda vague on handling threads and I haven't found a good example anywhere on the net.
-
May 24th, 2012, 02:52 AM
#10
Re: Stop a Thread
Originally Posted by cbpetro
...
When you use the boolean to stop the thread, the thread is only stopped. The m_pThread is still a pointer to CWinThread. It seems to me, there may be three conditions you may want to account for...
No, it is not correct.
When thread procedure returns thread terminates (exits).
You should not care about what still m_pThread points to, unless you haven't set the CWinThread::m_bAutoDelete to false. If you set it to false then you will have to delete this m_pThread object yourself.
You might want to check out this excellent Joe Newcomer's essay about Using Worker Threads
Victor Nijegorodov
-
May 25th, 2012, 03:51 PM
#11
Re: Stop a Thread
Originally Posted by cbpetro
... It seems to me, there may be three conditions you may want to account for....
No, as noted by VictorN, that's not correct. The thread ends when the thread function exits, so there is nothing left to "resume".
It is, of course, possible to write code for a thread pool, i.e., a pool of threads that sit idle until an event signals them that there is work to do. In such an architecture, threads can be "paused" and they can be "resumed". But that seems like something that you should aspire to in the future, not today.
For now, simply allow the thread to exit. If a user wants to start new thread-related work, then simply create a new thread.
Mike
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|