qt信号槽多线程死锁

时间:2013-05-24 18:29:32

标签: c++ multithreading qt

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

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

它调用工作线程的功能:

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

工作线程轮流检查_isFinished条件,如果没有设置,则发出信号。

对以下情况进行成像

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

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

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

我该如何处理?

2 个答案:

答案 0 :(得分:1)

这就是我看到的情况。

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

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

要使这项工作,您还需要在工作线程结束时关闭主窗口:

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

最后,所有使用_isFinished(以及工作线程中的所有其他变量)的操作都应该在工作线程中进行。你可以用一个简单的技巧来实现它:

<强> WorkerThread.h

public:
    void stop();

protected slots:
    void p_stop();

protected:
    QMutex mutex;

<强> WorkerThread.cpp

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

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

这样可以避免死锁。

答案 1 :(得分:0)

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

void stop() {
    QEventLoop eventloop;
    connect(&theWorkerThread, &QThread::finished, &eventloop, QEventLoop::quit);
    _isFinished = true;
    eventloop.exe();
}