user1888256
user1888256

Reputation: 167

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.

Upvotes: 8

Views: 38903

Answers (5)

Steven Tilly
Steven Tilly

Reputation: 91

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!

Upvotes: 9

selbie
selbie

Reputation: 104464

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);
}

Upvotes: 12

Zack Yezek
Zack Yezek

Reputation: 1483

Ultimately, you need to view each thread like a mini-process (that's what they are under the hood anyway). To get it to shutdown cleanly you need extra infrastructure in place that let's you- the main thread- tell it to stop.

The simplest way to do this right is a signalling system, which the inventors of POSIX figured out early on and thus expose directly in the OS. The best real-world example of such a system is the US Post Office. Every agent has a unique address from which they can both send and receive mail (signals) from other addresses, and it is up to the agent to decide what do when they get a signal. Some are info or junk, and thus ignored, whereas others are high priority and you ignore them at your peril.

At a code level you need the following to make that work well (I've built a few of these for image processing programs):
1) Some abstract "Event" or "ControlSignal" object. Feel free to use the default Windows events or linux signals if they're adequate.
2) A "Pipe" of some kind: The OS will often have a literal Kernel primitive CALLED a pipe that lets 1 end pull data off while another puts data in. This guy is usually overkill for comms within a process, but the object you need is conceptually equivalent.
3) Code within your threads that retrieves signals from the pipe and acts on them. 4) A "stop" or "cancel" signal all threads recognize.

Of course, you CAN just hard abort a thread with TerminateThread just as you can use taskkill or CTRL-C to kill a process. ExitThread is a Windows-specific way to build a clean shutdown signal like I describe in (4), but you still need the while-loop & "WaitForSingleObject" (3) plus the Windows-specific handle (2) to make it work.

Upvotes: 0

Ibrahim
Ibrahim

Reputation: 361

You can use SingleWaitObjects or QueueUserAPC but you have to make sure that the thread stops to check these async objects or wait for one in it's end and terminate the thread normally .. in linux you can use signals

Upvotes: 0

jweyrich
jweyrich

Reputation: 32240

Is your process supposed to finish when your thread is done? There could be a lot of explanations for the problem you described. If you want to terminate the entire process, just call ExitProcess.

The problem with TerminateThread is that is very likely to cause a memory leak. It doesn't care about the thread state, nor its allocated resources. It may also cause a deadlock, depending on how you're doing synchronisation. In other words, it does not terminate it gracefully.

The best way to terminate a thread is to not terminate it explicitly. Do not call TerminateThread nor ExitThread, but just return from the thread's function. You may need to use an atomic flag, or fire an event (or another synchronisation method) to signal when the thread should terminate. Then your thread should periodically check that flag (or event) and deallocate all resources before returning (terminating).

Upvotes: 2

Related Questions