【问题标题】:Qt Stop worker thread loop from GUI ThreadQt 从 GUI 线程停止工作线程循环
【发布时间】:2017-10-26 13:43:35
【问题描述】:

我有一个工作线程,我试图通过一个按钮来停止它。我有时会收到以下错误:

Fatal: QThread: Destroyed while thread is still running

这是我的代码。通过按下断开按钮,会发出一个信号来停止线程的 while 循环。

if (ui->connectButton->text() == "Connect") {
    mUDPThread = new QThread;
    mUDPWorker = new  UDPThread(ui->HostTextEdit->toPlainText(), ui->portTextEdit->toPlainText().toInt());
    mUDPWorker->moveToThread(mUDPThread);
    connect(mUDPThread, SIGNAL(started()), mUDPWorker, SLOT(process()));
    connect(mUDPWorker, SIGNAL(finished()), mUDPThread, SLOT(quit()));
    connect(mUDPWorker, SIGNAL(finished()), mUDPWorker, SLOT(deleteLater()));
    connect(mUDPWorker, SIGNAL(finished()), mUDPThread, SLOT(deleteLater()));
    connect(this, SIGNAL(onExitThread()), mUDPWorker, SLOT(onExitThread()));
    connect(this, SIGNAL(onDataIncome(QString)), mUDPWorker, SLOT(onDataIncome(QString)));
    mUDPThread->start();
    ui->connectButton->setText("Disconnect");
} else if (ui->connectButton->text() == "Disconnect") {
    emit onExitThread();
    ui->connectButton->setText("Connect");
}

工作线程:

void UDPThread::process() {
    while (isRunning) {
    QCoreApplication::processEvents();
      ...
    }
    emit finished();
}
void UDPThread::onExitThread() {
    qDebug() << "onExitThread" << isRunning;
    isRunning = false;
}

【问题讨论】:

    标签: c++ qt qthread


    【解决方案1】:

    while (isRunning)

    您正在那里阻塞线程,它的事件循环无法旋转以接收信号,它只能通过旋转事件循环向其他线程发送信号。

    您需要使您的工作人员不阻塞,将工作分成周期,在事件循环开始旋转和接收信号之间。在伪代码中:

    if (isRunning) {
      doWorkCycle();
      scheduleNextWorkCycle();
    } else emit finished();
    

    有一个例子你可以看看here

    【讨论】:

    • 抱歉,我当然会调用 processEvents() 并发出 finished()。我更新了问题
    • @momosxp 我不认为这有帮助,因为线程被阻塞了,它不会接收任何你可以强制处理的事件。即使它可以工作,必须手动调用processEvents() 也表明设计不佳。
    • 感谢您的帮助。我尝试使用invokemethod根据链接实现它。就像它在不使用 processEvents 的情况下工作一样,但它有时仍然会崩溃并显示相同的错误消息。
    • 我不知道它如何与 Qt 一起工作的实现细节,但是我链接到的示例无论如何都涵盖了您。有一些额外的冗长,必须拆分工作,以便可以在离散的步骤中完成,但如果你做了很多,你可以实现一个抽象类来重用并简单地实现初始化和工作步骤。
    【解决方案2】:

    解决了。错误出现在连接命令中:

    connect(mUDPWorker, SIGNAL(finished()), mUDPThread, SLOT(deleteLater()));
    

    connect(mUDPThread, SIGNAL(finished()), mUDPThread, SLOT(deleteLater()));
    

    结果:

    connect(mUDPThread, SIGNAL(started()), mUDPWorker, SLOT(process()));
    connect(mUDPWorker, SIGNAL(finished()), mUDPThread, SLOT(quit()));
    connect(mUDPWorker, SIGNAL(finished()), mUDPWorker, SLOT(deleteLater()));
    connect(mUDPThread, SIGNAL(finished()), mUDPThread, SLOT(deleteLater()));
    connect(this, SIGNAL(onExitThread()), mUDPWorker, SLOT(onExitThread()));
    connect(this, SIGNAL(onDataIncome(QString)), mUDPWorker, SLOT(onDataIncome(QString)));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-23
      • 1970-01-01
      • 2014-01-05
      • 2012-03-18
      • 1970-01-01
      • 2018-12-30
      • 1970-01-01
      • 2018-01-04
      相关资源
      最近更新 更多