18

最近,我在这个标题中提到了这个问题。我尝试过使用 QThread::terminate(),但我无法停止线程,它处于死循环中(比如说,while(1))。

多谢。

4

5 回答 5

12

终止线程是停止异步操作的简单解决方案,但这通常是一个坏主意:线程可能正在执行系统调用,或者在终止时可能正在更新数据结构,这可能会离开程序甚至操作系统处于不稳定状态。

尝试将您的 while(1) 转换为 while( isAlive() ) 并在您希望线程退出时使 isAlive() 返回 false。

于 2009-12-14T09:28:21.203 回答
1

如果 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);
  }
}
于 2011-12-29T12:06:37.390 回答
0

您是否尝试过退出退出

于 2009-12-14T02:27:37.143 回答
0

线程调用了QThread::setTerminationEnabled(false)吗?这将导致线程终止无限期延迟。

编辑:我不知道你在哪个平台上,但我检查了 QThread::terminate 的 Windows 实现。假设线程实际上开始运行,并且没有通过上述函数禁用终止,它基本上是TerminateThread()Windows API 中的一个包装器。此函数接受任何线程的不尊重,并且往往会留下资源泄漏和类似悬空状态的混乱。如果它没有杀死线程,那么您要么正在处理僵尸内核调用(很可能是阻塞的 I/O),要么在某个地方遇到了更大的问题。

于 2009-12-14T03:53:53.833 回答
0

使用未命名的管道

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,这增加了复杂性,调试是一场噩梦。除了简化代码之外,使用管道使我摆脱了这些复杂性。我并不是说它是最好的选择,但在我的情况下,它被证明是最好和最干净的选择。在这个解决方案之前,我被挂起的应用程序窃听了。

于 2010-01-09T12:50:43.387 回答