Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stop thread safely

i write multi thread program.

I want to ask what is difference between TerminateThread and ExitThread?

This is my code snippet when WM_DESTROY received :

void CleanAll()
{
    DWORD dwExit[MAX_THREAD];
    for(int i = 0; i < MAX_THREAD; i++)
    {
        GetExitCodeThread(hThread[i], &dwExit[i]);
        // I used ExitThread(dwExit[i]); previously
        TerminateThread(hThread[i], dwExit[i]);
        CloseHandle(hThread[i]);
    }
}

I used ExitThread() previously, but my program stikk in Task Manager, so I change it to TerminateThread() and my program is gone from Task Manager.

Any advance explanation is very appreciated.

like image 629
user1888256 Avatar asked Dec 16 '12 03:12

user1888256


2 Answers

TerminateThread forces another thread to exit. You should avoid calling it at all costs as it will stop a thread dead in it's tracks without any chance to cleanup. This includes any CRT memory allocated.

ExitThread is for the currently running thread to stop itself nice and cleanly. When you called it above, you likely forced the main (UI) thread to exit and likely left the running threads still lingering around. Hence, your program was still running as evidenced in Task Manager. GetExitCodeThread was also likely failing since the threads had not actually exited.

But the right way to stop a thread is to cleanly signal by any clean means necessary that it should exit. Then allow the threads to exit on their own before allowing the main thread to exit. In the following example, I used a global flag to indicate to threads that they should exit. But that assumes your threads will always have a chance to poll for the global bool state. Another cleaner approach is to have each thread call WaitForSingleObject on an event handle. When the event handle is signalled, the thread checks the global variable and exits if needed.

bool global_Need_ToExit;  // use a bool or replace with an event handle the thread shoudl wait on

void CleanAll()
{
    //signal all threads to exit
    global_Need_ToExit = true;

    DWORD dwExit[MAX_THREAD];
    for(int i = 0; i < MAX_THREAD; i++)
    {
        // actually wait for the thread to exit
        WaitForSingleObject(hThread[i], WAIT_INFINITE);

        // get the thread's exit code (I'm not sure why you need it)
        GetExitCodeThread(hThread[i], &dwExit[i]);

        // cleanup the thread
        CloseHandle(hThread[i]);
        hThread[i] = NULL;
    }
}

DWORD __stdcall YourThreadFunction(void* pData)
{

    while (global_Need_To_Exit == false)
    {
        // do more work
    }

    return 0; // same as ExitThread(0);
}
like image 130
selbie Avatar answered Sep 27 '22 19:09

selbie


Sorry, but the top voted answer says to use ExitThread because it will "stop itself nice and cleanly". This is simply not true. The documentation states: ExitThread is the preferred method of exiting a thread in C code. However, in C++ code, the thread is exited before any destructors can be called or any other automatic cleanup can be performed. Therefore, in C++ code, you should return from your thread function. I learned this the hard way by following advice from a forum to use ExitThread and then spending hours wondering where the heck all my memory leaks were coming from. Yeah, that's for C++, but that's what this question is regarding. And actually, even for C there is a caveat "A thread in an executable that is linked to the static C run-time library (CRT) should use _beginthread and _endthread for thread management rather than CreateThread and ExitThread. Failure to do so results in small memory leaks when the thread calls ExitThread." DO NOT USE ExitThread without being aware of the consequences!

like image 21
Steven Tilly Avatar answered Sep 27 '22 21:09

Steven Tilly