【问题标题】:How to exit from QThread::wait()如何退出 QThread::wait()
【发布时间】:2018-06-27 13:48:37
【问题描述】:

我在后台使用 QThread 执行一些大型任务,这里是示例 我正在使用的代码

class Worker : public QObject
{
    Q_OBJECT
    QThread workerThread;

public slots:
    void doWork(const QString &parameter) {
        while(1){         
          // some huge code here
           ......................


          if(condition) break;
       }

        emit resultReady(result);
    }

signals:
    void resultReady(const QString &result);
};

class Controller : public QObject
{
    Q_OBJECT
    QThread workerThread;
public:
    Controller() {
        Worker *worker = new Worker;
        worker->moveToThread(&workerThread);
        connect(&workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
        connect(this, SIGNAL(operate(QString)), worker, SLOT(doWork(QString)));
        connect(worker, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
        workerThread.start();
    }
    ~Controller() {
        workerThread.quit();
        workerThread.wait();
    }
public slots:
    void handleResults(const QString &);
signals:
    void operate(const QString &);
};

上面的程序退出后是否推荐使用wait()? 我的程序有时卡在QThread::wait(),它正在从服务器下载巨大的文件,再次检查while条件大约需要5-6分钟,我只想退出线程但主线程卡在wait(),有没有大大地??在不崩溃或挂起主应用程序的情况下强行退出或终止线程?我也试过QThread::terminated,但它从来没有用过。 任何帮助表示赞赏。 谢谢。

【问题讨论】:

  • 你试过调试你的线程函数吗?可以暂停一个进程并观察现在执行的代码。
  • 是的,它永远不会退出 while 循环 @DmitrySazonov
  • 那么,问题解决了吗?

标签: c++ multithreading qt qt4 qthread


【解决方案1】:

QThread 类的官方文档说:

bool QThread::wait(unsigned long time = ULONG_MAX)

阻塞线程直到满足以下任一条件:

  • 与此 QThread 对象关联的线程已完成执行(即当它从 run() 返回时)。如果线程已完成,此函数将返回 true。如果线程尚未启动,它也会返回 true。

  • 时间毫秒已经过去。如果时间为 ULONG_MAX(默认值),则等待永远不会超时(线程必须从 run() 返回)。如果等待超时,此函数将返回 false。

如您所见,ULONG_MAX 是该方法的默认参数,它强制该方法永不超时。

是否可以选择在方法参数中添加自己的超时时间?

【讨论】:

  • 超时将从 QThread::wait 退出,但线程仍在后台运行
【解决方案2】:

首先,从上述代码中不清楚您在线程中做了什么。您的第一个关注点是您在线程内运行的方法,即您的线程对象。首先,为什么有时你的线程没有完成它的任务?为什么它卡住了?在这里,我可以看到一个while 循环,其条件始终为真。可能你在循环中有一些 break 语句,它有时永远不会满足,因为当循环继续时,线程永远不会完成。只需仔细检查那里出了什么问题。如果 while 循环正在创建问题,我可以建议您在代码中进行以下修改。但是你必须非常小心,因为它不应该在完成一些非常重要的任务之前退出。

首先修改您的 while 循环,如下所示:- 在while循环前引入一个bool变量

bool continued = true;
while(continued)
{
   //your codes
}

现在在你的线程对象 Worker 中添加一个方法

void stopWorker()
{
   continued = false;
}

现在,当您希望线程强制退出时,只需调用此方法
worker->stopWorker();

【讨论】:

  • continue 是保留字,换一个。
  • 是的。修改的。谢谢
  • @p-a-o-l-o,是的,您可以从其他线程甚至主线程执行此操作。
  • 你确定它是安全的吗?想得更好。
  • 这里你强制线程提前退出。因此,我在回答中写道,您必须非常小心地使用它。
【解决方案3】:

从 Qt 5.2 开始,有一个 QThread::requestInterruption() 单独这个函数可以用来向你的线程发出信号它应该停止工作,但是你必须检查您对 QThread::isInterruptionRequested() 的长时间操作并退出您的循环或事件循环: http://doc.qt.io/qt-5/qthread.html#isInterruptionRequested

【讨论】: