当进程结束时,处于Sleep()中间的线程会发生什么



我正在处理一个启动和结束线程的类。线程是在构造函数中创建的。只要标志为TRUE,线程函数就会有一个循环。标志是类的静态成员。解构器将标志设置为FALSE。这样,类的每个实例都有一个关联的线程,该线程在实例的生存期内运行。

我试着思考解构器运行时会发生什么,以及这是否是结束线程的好方法。我对多线程没有太多经验。

以下是我认为会发生的事情。在解构器内部,标志将被设置为FALSE。让我们假设Sleep()正在为无穷大运行。对象已被销毁,但该标志仍然存在于内存中,因为它是静态的。但是,比方说,整个过程正在结束,所以在某个时刻,静态标志将消失。标志会在线程之前消失吗?如果进程结束时线程被迫返回,那么线程还会关心标志吗?我不知道此刻发生了什么。

我在Visual Studio 2010中使用Visual C++。

请注意,在其他线程仍在使用该对象(而不是静态标志)时运行析构函数将产生未定义的结果。

想想当线程在处理过程中而不是检查活动标志时会发生什么,几率很小。

最好编写一个stop(bool-wait)函数,因此如果析构函数被调用并需要自动清理,则将标志设置为stop,并阻塞直到线程将另一个标志设置为"stop",或者只使用pthread_join连接该线程(不推荐使用,请参阅下文)。

此外,当您阻止优雅的终止时,您还可以设置超时,并在出现问题时强制终止线程(并生成调试警报)。

在Windows上,线程的生存期小于或等于它所在的进程。因此,一旦进程结束,线程也会结束。

在进程中的所有线程终止之前,正常的进程关闭不会完成。因此,在这种情况下,将设置标志,主线程可能终止,但创建的后台线程将继续运行。最终,他们将看到标志的FALSE值,退出循环,完成流程关闭。

这取决于"解构器"是否真的运行。

如果你试图"解构"你在某个"OnClose"事件处理程序中描述的对象,设置静态标志将指示线程在检查时终止。如果不这样做,线程将继续休眠(或停留在任何阻塞的调用上,或继续运行代码)。

如果您不采取进一步的操作来等待对象线程终止,主GUI线程将在上运行,销毁其所有GUI对象等,并调用ExitProcess()。

调用ExitProcess()后,操作系统将停止进程的所有线程,无论它们处于何种状态,然后再释放任何内存(如包含您的标志的内存)。

调用ExitProcess()的线程永远不会返回控制权。属于同一进程并且没有在另一个核心上运行的其他线程都设置了状态,这样它们就再也不会运行了。属于同一进程并在另一个内核上运行的其他线程会中断它们在硬件上运行的内核以停止线程。

标志会在线程之前消失吗?

否。在释放承载该标志的内存之前,线程将停止。

如果您不希望发生这种强制终止,则必须采取措施等待对象线程的实际终止。您必须通过在OnClose处理程序中设置适当的CloseAction来延迟主GUI线程调用ExitProcess。只有当所有对象线程都已终止并且对象的析构函数已完成时,GUI线程才应该关闭/释放自己。

如果我真的,真的,确实必须这样做,我更喜欢通过向主GUI线程发布一条"WM_THREADONE"Windows消息来完成,(作为对象线程在实际终止它们之前的最后一个操作),并在消息处理程序中向零倒计数"threadCount",从而保持GUI线程可用于处理消息,直到所有对象线程都终止了它们自己。像Join()这样的Hard Wait机制只是死锁生成器,它具有巨大的关闭问题容量,不应该使用。

我通常会尝试通过设计我的应用程序来解决所有线程终止问题,这样突然的、非自愿的线程终止就可以接受了,然后让Exitprocess()把一切都搞砸。这并不总是可能的,但如果你能逃脱惩罚,它会更安全。

最新更新