在退出进程时等待线程完成

Posted

技术标签:

【中文标题】在退出进程时等待线程完成【英文标题】:Waiting on threads to finish while quitting the process 【发布时间】:2016-03-11 23:05:44 【问题描述】:

在一个相当简单的问题上没有找到直接和令人满意的答案:

鉴于多个线程正在运行,是否有一种通用/正确的方法可以在退出进程时等待它们完成? 或者“在这种情况下是否正在执行定时等待?”

是的,我们尝试向线程发出信号以结束,但观察到在进程退出期间,其中一些线程往往会停止。我们最近进行了一次讨论,并决定摆脱“任意等待”:

m_thread.quit();          // the way we had threads finished
m_thread.wait(kWaitMs);   // with some significant expiration (~1000ms)

m_thread.quit();          // the way we have threads finished now
m_thread.wait();          // wait forever until finished

我知道 kWaitMs 常数的选择应该与线程完成的一个不间断“作业周期”成比例。比如说,如果线程处理一些数据块 10 毫秒,那么我们可能应该等待它响应退出信号 100 毫秒,如果它仍然没有退出,那么我们就不再等待了。只要我们退出程序并且不再关心,我们就不会在这种情况下等待。但有些工程师不理解这样的“范式”,想要一个终极的等待。请注意,在我们的案例中,卡在客户端计算机内存中的程序进程将导致下一次程序启动时出现问题,更不用说日志将无法正确完成以作为错误处理。

可以回答关于进程退出时正确完成线程的问题吗?

Qt/API 是否提供了一些帮助来更好地解决线程挂起问题,以便我们记录其原因?

附:请注意,我是well aware,为什么强行终止线程是错误的以及如何做到这一点。我猜这个问题不是关于同步,而是关于运行大量我们和框架和操作系统代码的线程的有限确定性。操作系统不是实时的,对吧:Windows / MacOS / Linux 等。

P.P.S.所有有问题的线程都有事件循环,因此它们应该响应QThread::quit()

【问题讨论】:

那么,您是在问如何确保线程正确响应“退出”事件?或者,您是在问如何确定线程没有正确退出的原因?我不确定我理解你所说的“有限决定论”是什么意思。您的意思是“确保它不能运行很长时间”? 主要问题:在这种情况下,做定时等待好吗?以及所有相关的讨论,包括为什么它不退出的诊断。 【参考方案1】:

是的,我们尝试向线程发出信号以结束,但观察到 在进程退出期间,其中一些往往会停止。

这是你真正的问题。您需要弄清楚为什么您的某些线程会停止,并修复它们,以便它们不会停止并且总是在它们应该停止时可靠地退出。 (他们退出的确切时间并不那么重要,只要他们在合理的时间内退出,即在用户厌倦等待并强制退出整个应用程序之前)

如果您不/不能这样做,则无法可靠地关闭您的应用,因为您无法安全地释放线程可能仍在访问的任何资源。在主线程调用线程使用的任何对象(例如与线程关联的 QThread 对象)的析构函数之前,必须 100% 保证线程已经退出

所以总结一下:不要费心玩等待超时或强制终止线程的游戏;所有这一切都会让你得到一个有时会在关机时崩溃的应用程序。使用无限期等待,并确保您的线程总是(总是!)在主线程要求它们退出后退出,因为这是实现可靠关闭序列的唯一方法。

【讨论】:

顺便说一句,当您遇到在关闭序列期间停止的线程时,最好使用调试器或类似 Apple 活动监视器的“示例进程”功能的东西找出哪里线程的当前执行点是(即它被卡住的位置的堆栈跟踪)。一旦你知道线程卡在哪里,你就可以很好地找出卡住的原因,并弄清楚如何解开它。 我不能不同意你找到这种麻烦的原因,但是当它发生在“现场”时有点太晚了。也许让调试代码不关注“过期”期间而仍然无限等待发布代码是有意义的。 同意,“现场”为时已晚——这意味着问题需要在“场外”重现并在此之前解决,如果可能的话。

以上是关于在退出进程时等待线程完成的主要内容,如果未能解决你的问题,请参考以下文章

linux线程的创建、退出、等待、取消、分离

获取前一段时间完成的后台进程的退出代码

Linux系统编程(进程)———进程退出

Linux系统编程(进程)———进程退出

Linux系统编程(进程)———进程退出

Linux系统编程(进程)———进程退出