为什么子类QThread无法启动?

时间:2016-07-20 21:03:53

标签: multithreading qt

这是基于白皮书“QThreads:你没有这么做错”中表达的想法使用子类QThread。它没有事件循环,也没有插槽。它只是发出信号并停止。实际上它的主要信号是QThread finished

基本上我有一个Qt使用后台线程来监控东西。在找到它要查找的内容后,它会记录其数据并终止。

终止向应用程序的主事件循环部分发送信号,该部分处理它,并在完成后重新启动背景。我通常可以让这个工作几十秒,但它似乎就好了。

似乎当主应用程序尝试启动该线程时,它并没有真正运行。我将此基于遥测代码,该代码在程序执行时递增计数器。

基本上

//in main application.  Setup not shown. 
//background points to the QThread sub-class object
void MainWindow::StartBackground()
{
    background->startcount++;
    background->start();

    if ( background->isRunning() )
    {
        background->startedcount++;
    }
}


//in sub-classed QThread
void Background::run()
{
    runcount++;

    //Do stuff until done
}

因此,当我注意到我的后台线程似乎没有运行时,通过观察Process Explorer,我导致调试器中断,并检查计数。我看到的是startcountstartedcount是平等的。并且值大于runcount

所以我只能得出结论说线程没有真正运行,但我无法找到任何证据证明原因。

我无法找到关于QThreads的文档,没有开始做某些错误条件,或者有什么证据表明存在这样的错误。

我想我可以设置一个插槽来捕获线程中的started。启动代码可以在超时信号量上循环,一次又一次地尝试,直到started插槽实际重置信号量。但它感觉很难看。

编辑 - 更多信息

因此,使用信号量方法,我有办法在无法启动时断点。

我想在isFinished()之前就对start()进行了抽样,这是假的。在我的100ms信号量超时后,它变成了现实。

所以这个问题似乎正演变成'为什么QThread有时会在finished()变为真之前发出isFinished()信号?

了解种族情况。我不想在开始下一个后台线程之前转动isFinished()

所以这可能是

的副本

QThread emits finished() signal but isRunning() returns true and isFinished() returns false

但不完全是,因为我覆盖run()并且我没有事件循环。

特别是该答案中的事件8和9的顺序不同。我的广告位在finished()成立之前获得isFinished()

我不确定明确quit()与让run()返回有什么不同;

2 个答案:

答案 0 :(得分:0)

听起来好像你有一个竞争条件,你可能会在上一次迭代实际完成之前尝试重新启动你的线程。如果是这样的话,那么从我看到的情况来看,对QThread::start的下一次调用将被默默地忽略。您需要更新代码,以便在重新启动之前检查线程的状态 - 通过调用QThread::isFinished或处理QThread::finished信号。

另一方面......为什么线程反复启动/停止。简单地启动一次线程会不容易?无论在QThread::run的上下文中运行什么代码,都可以监视它监视的内容,并在发现任何注意事项时发出主应用程序的信号。

更好。 Separate the monitor logic from the thread entirely...

class monitor: public QObject {
    .
    .
    .
};

QThread monitor_thread;
monitor monitor;

/*
 * Fix up any signals to/from monitor.
 */
monitor.moveToThread(&monitor_thread);
monitor_thread.start();

monitor课程可以做任何想做的事情,当退出应用程序时,只需拨打monitor_thread::quit

答案 1 :(得分:0)

我正在使用的Qt版本中存在竞争条件。我以前不知道是否有报道,但我没有最新版本,所以除非我能在当前版本中展示它,否则它可能没有实际意义。

很久以前就报道了类似的错误:

QThread.isFinished returns False in slot connected to finished() signal

(我使用的版本比Qt 4.8.5更新)

更重要的是我可以使用以下代码解决它

while ( isRunning() )
{
    msleep(1);
}
start();

我已经进行了一些测试,并且似乎从未花费超过1毫秒的竞争条件来解决。可能只需要一个上下文切换来清理。