C++ 安全停止线程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13898372/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:48:36  来源:igfitidea点击:

Stop thread safely

c++multithreadingwinapi

提问by user1888256

i write multi thread program.

我写多线程程序。

I want to ask what is difference between TerminateThreadand ExitThread?

我想问一下TerminateThread和 和有什么不一样ExitThread

This is my code snippet when WM_DESTROYreceived :

这是我WM_DESTROY收到时的代码片段:

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.

ExitThread()以前使用过,但是我的程序在任务管理器中被粘住了,所以我将其更改为TerminateThread()并且我的程序从任务管理器中消失了。

Any advance explanation is very appreciated.

任何预先解释都非常感谢。

回答by selbie

TerminateThread forces another threadto 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.

TerminateThread 强制另一个线程退出。你应该不惜一切代价避免调用它,因为它会阻止一个线程死在它的轨道上而没有任何清理机会。这包括分配的任何 CRT 内存。

ExitThread is for the currently running threadto 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.

ExitThread 用于当前正在运行的线程很好地和干净地停止自己。当您在上面调用它时,您可能会强制主 (UI) 线程退出并可能使正在运行的线程仍然徘徊。因此,正如任务管理器中所证明的那样,您的程序仍在运行。GetExitCodeThread 也可能失败,因为线程实际上并未退出。

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 ownbefore 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 状态。另一种更简洁的方法是让每个线程在事件句柄上调用 WaitForSingleObject。当事件句柄发出信号时,线程检查全局变量并在需要时退出。

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

回答by Steven Tilly

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!

对不起,但投票最高的答案说使用 ExitThread 因为它会“很好地和干净地停止自己”。这是不正确的。文档指出: ExitThread 是退出 C 代码中线程的首选方法。但是,在 C++ 代码中,线程会在调用任何析构函数或执行任何其他自动清理之前退出。因此,在 C++ 代码中,您应该从线程函数中返回。我通过遵循论坛上的建议使用 ExitThread 艰难地学到了这一点,然后花了几个小时想知道我所有的内存泄漏到底是从哪里来的。是的,那是针对 C++ 的,但这就是这个问题所涉及的。实际上,即使对于 C 也有一个警告“链接到静态 C 运行时库 (CRT) 的可执行文件中的线程应该使用 _beginthread 和 _endthread 进行线程管理,而不是使用 CreateThread 和 ExitThread。如果不这样做,会在线程调用 ExitThread 时导致小内存泄漏。” 不要在没有意识到后果的情况下使用 ExitThread!

回答by jweyrich

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.

当您的线程完成时,您的进程是否应该完成?您描述的问题可能有很多解释。如果要终止整个过程,只需调用ExitProcess.

The problem with TerminateThreadis 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.

问题TerminateThread在于这很可能导致内存泄漏。它不关心线程状态,也不关心它分配的资源。它也可能导致死锁,具体取决于您如何进行同步。换句话说,它不会优雅地终止它。

The best way to terminate a thread is to not terminate it explicitly. Do not call TerminateThreadnor ExitThread, but just returnfrom 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).

终止线程的最佳方法是不显式终止它。不要调用TerminateThreadnor ExitThread,而只是return从线程的函数中调用。您可能需要使用原子标志,或触发事件(或其他同步方法)来通知线程何时终止。然后您的线程应该定期检查该标志(或事件)并在返回(终止)之前释放所有资源。

回答by Ibrahim

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

您可以使用 SingleWaitObjects 或 QueueUserAPC 但您必须确保线程停止检查这些异步对象或等待它结束并正常终止线程..在 linux 中您可以使用信号

回答by Zack Yezek

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.

正确执行此操作的最简单方法是信号系统,POSIX 的发明者很早就想到了这一点,因此直接在操作系统中公开。这种系统在现实世界中最好的例子是美国邮局。每个代理都有一个唯一的地址,他们可以从该地址发送和接收来自其他地址的邮件(信号),当他们收到信号时,由代理决定做什么。有些是信息或垃圾,因此被忽略,而另一些则是高优先级,你忽略它们会带来危险。

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.

在代码级别,您需要以下内容才能使其正常工作(我已经为图像处理程序构建了其中一些):
1) 一些抽象的“事件”或“控制信号”对象。如果足够,请随意使用默认的 Windows 事件或 linux 信号。
2)某种“管道”:操作系统通常会有一个字面的内核原语称为管道,它让一端拉出数据,而另一端将数据放入。这家伙通常对进程内的通信有点过分,但是你的对象需要在概念上是等价的。
3) 线程中的代码从管道中检索信号并对其进行操作。4) “停止”或“取消”信号表示所有线程识别。

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.

当然,您可以使用 TerminateThread 硬中止线程,就像您可以使用 taskkill 或 CTRL-C 来终止进程一样。ExitThread 是一种特定于 Windows 的方法来构建一个干净的关闭信号,就像我在 (4) 中描述的那样,但是您仍然需要 while 循环和“WaitForSingleObject”(3) 加上特定于 Windows 的句柄 (2) 才能使其工作。