【问题标题】:QThread: slot quit() is never invoked and hence the thread wait() is foreverQThread: slot quit() 永远不会被调用,因此线程 wait() 是永远的
【发布时间】:2020-12-06 11:03:55
【问题描述】:

我遇到了与QThread won't stop / does not process a signal 描述的完全相同的问题,但有一点不同。即使在我的while循环中使用QCoreApplication::processEvents(),我也无法让它工作。我关注了这个blog post,结果如下:

MediaController.cpp

void MediaController::buttonPlayClicked(bool checked)
{
    if (checked)
    {
        m_loopThread = new QThread;
        m_playPauseworker = new PlayPauseWorker;
        m_playPauseworker->moveToThread(m_loopThread);
        connect(m_playPauseworker, &PlayPauseWorker::dataReady, this, &MediaController::onDataReady);
        connect(m_loopThread, &QThread::started, m_playPauseworker, &PlayPauseWorker::process);

        connect(m_playPauseworker, &PlayPauseWorker::finished, m_loopThread, &QThread::quit); // <-- never works
       
        connect(m_playPauseworker, &PlayPauseWorker::finished, m_playPauseworker, &PlayPauseWorker::deleteLater);
        connect(m_loopThread, &QThread::finished, m_loopThread, &QThread::deleteLater);
        m_loopThread->start();
    }
    else
    {
        m_loopThread->requestInterruption();
    }
}

每次单击播放/暂停可检查按钮时都会调用上述插槽。在主线程上创建线程和worker。

PlayPauseWorker.cpp

void PlayPauseWorker::process()
{
    while (!QThread::currentThread()->isInterruptionRequested())
    {
            // heavy computations

            emit dataReady(std::tuple<QImage, QImage, QImage>>); // <-- works!
            
            QCoreApplication::processEvents(); // <-- doesn't help with quit()
    }           

    emit finished(); // <-- emits the signal but quit() not called
}

在进一步处理时,当我访问wait() 以查看我的线程是否已退出时,它永远不会返回。

除了从未调用过quit() 插槽之外,我注意到当线程运行时我的 GUI 变得非常不稳定。我有时可以/不能点击其他按钮或玩 UI。我浏览了很多 SO 帖子,但无法找到一种在需要时干净地退出线程的方法。不知道我哪里错了。

【问题讨论】:

  • 明确地说,一旦单击播放按钮,您的 GUI 就没有响应?如果 GUI 无响应,您如何调用 requestInterruption
  • 注释掉connect(m_playPauseworker, &amp;PlayPauseWorker::dataReady, this, &amp;MediaController::onDataReady);是否有效?
  • @m7913d 关于 GUI 无响应我编辑了我的问题。注释掉连接语句不起作用。
  • 我自己无法复制这个;我整理了一个测试(没有 UI),其中有几个类的行为类似于您的 MediaControllerPlayPauseWorker,并且看到线程退出。我不确定繁重的计算是否会破坏信号/插槽处理,但我不这么认为。请检查您是否在正确的线程上调用wait()。我在测试中没有使用wait(),而是使用connect(thread, &amp;QObject::destroyed, [] { std::cout &lt;&lt; "destroyed" &lt;&lt; std::endl; }); 来查看线程何时被销毁;可以试试吗?
  • 我还在测试中注意到QCoreApplication::processEvents() 实际上并不需要事件传播到主线程。至于断断续续的问题,您可以通过将侧线程的线程优先级设置为较低来缓解一些问题?

标签: c++ multithreading qt qthread


【解决方案1】:

尝试了很多建议后,我仍然无法弄清楚为什么emit finished() 没有退出线程。所以,作为最后的手段,我使用this-&gt;thread-&gt;quit() 来达到同样的效果。

但感谢这里的所有评论者,我缩小了滞后/不稳定的 gui 问题。 我的emit data(std::tuple&lt;QImage, QImage, QImage&gt;&gt;) 在循环中设置QGraphicsScene 上的像素图,而没有删除场景中已经设置的像素图,导致大量内存泄漏并最终崩溃。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-27
    • 2013-10-12
    • 2012-03-27
    • 2013-08-29
    • 2013-11-03
    • 1970-01-01
    • 1970-01-01
    • 2015-05-06
    相关资源
    最近更新 更多