如何终止 QThread
Posted
技术标签:
【中文标题】如何终止 QThread【英文标题】:How can I terminate a QThread 【发布时间】:2010-12-26 07:10:51 【问题描述】:最近,我在这个标题中提到了这个问题。 我尝试过使用 QThread::terminate(),但我无法停止 处于死循环中的线程(比如说,while(1))。
非常感谢。
【问题讨论】:
重新标记以添加更常见的“qt”标签。 Qt 文档说:“警告:这个函数很危险,不鼓励使用。线程可以在其代码路径中的任何位置终止。线程可以在修改数据时终止。没有线程有机会自行清理,解锁任何持有的互斥锁等。简而言之,仅在绝对必要时使用此函数。可以通过调用 QThread::setTerminationEnabled() 显式启用或禁用终止。在禁用终止时调用此函数导致终止被推迟,直到重新启用终止。" 【参考方案1】:你试过exit或quit吗?
【讨论】:
QT 帮助文档中的引用:“如果线程没有事件循环,这个函数什么都不做” 在事件循环的情况下它可能会起作用。但是如果我想在线程完成它的工作之前终止它,我应该怎么做?多谢。亲爱的。 事实上,这两个函数实际上是用于在调用 exec 时从事件循环中返回。【参考方案2】:线程调用QThread::setTerminationEnabled(false)
了吗?这将导致线程终止无限期延迟。
编辑:我不知道你在哪个平台上,但我检查了 QThread::terminate 的 Windows 实现。假设线程实际上开始运行,并且没有通过上述函数禁用终止,它基本上是 Windows API 中 TerminateThread()
的包装器。此函数接受任何线程的不尊重,并且往往会留下资源泄漏和类似悬空状态的混乱。如果它没有杀死线程,那么您要么正在处理僵尸内核调用(很可能是阻塞的 I/O),要么在某个地方遇到了更大的问题。
【讨论】:
我让它调用 setTerminationEnabled(true);【参考方案3】:终止线程是停止异步操作的简单解决方案,但这通常是一个坏主意:线程可能正在执行系统调用,或者在终止时可能正在更新数据结构,这可能让程序甚至操作系统处于不稳定状态。
尝试将您的 while(1) 转换为 while(isAlive()) 并在您希望线程退出时使 isAlive() 返回 false。
【讨论】:
嗨,rpg。 while(1) 的例子只是一种情况。我真正想要的是终止正在执行大量计算且将持续很长时间的线程。我只想在它完成执行之前停止它。谢谢。 ps:我看到了Rocknroll给出的线索--use pipe to stop a Qthread。但是我从来没有找到解决方案。 尝试在繁重的计算函数中添加类似于中断点的内容:justsoftwaresolutions.co.uk/threading/… 是的,我同意这里所说的。以硬方式终止线程绝不是一件好事。【参考方案4】:使用未命名的管道
int gPipeFdTest[2]; //create a global integer array
当您打算创建管道时使用
if( pipe(gPipeFdTest) < 0)
perror("Pipe failed");
exit(1);
上面的代码将创建一个管道,它有两端 gPipeFdTest[0] 用于读取和 gPipeFdTest[1] 用于写入。您可以做的是在您的运行函数中设置为使用 select 系统调用读取管道。并且从你想跑出来的地方,那里设置写使用写系统调用。我已经使用 select 系统调用来监视管道的读取端,因为它适合我的实现。试着在你的情况下弄清楚这一切。如果您需要更多帮助,请给我留言。
编辑:
我的问题和你的一样。我有一个 while(1) 循环,而我尝试的其他事情需要互斥锁和其他花哨的多线程 mumbo jumbo,这增加了复杂性,调试是一场噩梦。除了简化代码之外,使用管道使我摆脱了这些复杂性。我并不是说这是最好的选择,但在我的情况下,它被证明是最好和最干净的选择。在这个解决方案之前,我被挂起的应用程序窃听了。
【讨论】:
【参考方案5】:如果 QThread 在终止期间“自然”完成,它们可能会死锁。
例如在 Unix 中,如果线程正在等待“读取”调用,则终止尝试(Unix 信号)将使“读取”调用在线程被销毁之前以错误代码中止。
这意味着线程在被终止时仍然可以到达它的自然退出点。当它这样做时,会发生死锁,因为某些内部互斥体已经被“终止”调用锁定。
我的解决方法是确保线程永远不会在被终止时返回。
while( read(...) > 0 )
// Do stuff...
while( wasTerminated )
sleep(1);
return;
wasTerminated 这里的实现其实有点复杂,使用原子整数:
enum
Running, Terminating, Quitting
;
QAtomicInt _state; // Initialized to Running
void myTerminate()
if( _state.testAndSetAquire(Running, Terminating) )
terminate();
void run()
[...]
while(read(...) > 0 )
[...]
if( !_state.testAndSetAquire(Running, Quitting) )
for(;;) sleep(1);
【讨论】:
以上是关于如何终止 QThread的主要内容,如果未能解决你的问题,请参考以下文章