1

在我的代码中,工作线程向 gui 线程发出信号。Signal 和 Slot 通过 Qt::BlockingQueuedConnection 连接。

closeEvent应用程序在尝试停止工作线程时,才完成事件。

它调用工作线程的函数:

void stop() {
  _isFinished = true;
  wait();
}

工作线程依次检查_isFinished条件,如果未设置,则发出信号。

成像以下情况

The worker            Gui Thread 
=================     =================
if (!_isFinished)     -----------------
-----------------     _isFinished = true;
-----------------     wait();
emit mySignal();      -----------------

显然,两个线程都会被锁定——死锁。

如果我添加一个互斥锁,那么您会发现另一个死锁情况。当工作人员锁定互斥锁时,gui线程将被阻塞。结果,发出的信号将锁定工作人员。

我该如何处理?

4

2 回答 2

1

这就是我看到的情况。

在您的主线程中,您无需等待工作人员退出。相反,您closeEvent应该如下所示:

if (workerThread->isRunning())
{
    workerThread->stop();
    event->ignore();
}

要完成这项工作,您还需要在工作线程完成时关闭主窗口:

connect(workerThread, SIGNAL(finished()), SLOT(close()));

最后,所有操作_isFinished(以及工作线程中的所有其他变量)都应该发生在工作线程中。您可以通过一个简单的技巧来实现它:

工作线程.h

public:
    void stop();

protected slots:
    void p_stop();

protected:
    QMutex mutex;

工作线程.cpp

void WorkerThread::stop()
{
    staticMetaObject.invokeMethod(this, "p_stop", Qt::QueuedConnection);
}

void WorkerThread::p_stop();
{
    QMutexLocker locker(&mutex);
    _isFinished = true;
}

这样可以避免死锁。

于 2013-05-24T19:21:13.983 回答
0

在 gui 线程中,您可以使用 QEventLoop 等待。看起来像这样:

void stop() {
    QEventLoop eventloop;
    connect(&theWorkerThread, &QThread::finished, &eventloop, QEventLoop::quit);
    _isFinished = true;
    eventloop.exe();
}
于 2021-03-29T03:29:48.557 回答