Qt通过QConcurrent :: run终止线程生成

时间:2013-03-13 04:42:15

标签: c++ qt qthread qtconcurrent

平台:Win7 x64,MinGW-rubenvb(4.7.2-x64),Qt 4.8

假设我使用QConcurrent :: run生成了很少的冗长任务(读取填充文件,写入填充文件和运行模拟),如下所示:

void MainWindow::runLengthyJob() {
    /* some setup */
    jobWatcher->setFuture(QConcurrent::run(theApp, &AppClass::lengthyJob));
    // lengthyJob - can be readPop(), writePop(), runSim()
}

通常这些任务至少需要15秒才能完成(对于模拟,需要花费超过数小时)。为了防止从尚未完成的线程崩溃,我重新实现了MainWindow :: closeEvent,如下所示:

void MainWindow::closeEvent(QCloseEvent *event) {
    /* wait for any dangling thread */
    if (QThreadPool::globalInstance()->activeThreadCount())
        QThreadPool::globalInstance()->waitForDone();
    event->accept();
} // end: MainWindow::closeEvent

这样可以正常工作但是当我点击MainWindow的'x'按钮时,它看起来很冷,显示'没有响应'(我猜文本是由操作系统提供的),虽然它最终终止了应用程序。

我想在触发MainWindow的close()插槽后立即退出应用程序。那么,我怎样才能缩短尚未完成的线程的等待时间?或者我如何通知用户仍有长时间的作业运行(可能需要几个小时才能完全关闭)? (我试图在closeEvent中包含QDialog / QMessagebox,但新创建的小部件也会冻结)

注意:对于AppClass:lengthyJobs [readPop()/ writePop()],这些是自包含的函数,我不能分解为较小的步骤。对于AppClass :: runSim(),可能会采用较小的步骤。

1 个答案:

答案 0 :(得分:0)

首先,QtConcurrent :: run返回的未来不支持取消。所以你不能取消它。你可以做的最好的事情是在AppClass中设置一些标志并在你的longyJobs中检查它(正如你所说的那样在runSim的情况下),然后等待完成。

无论哪种方式,如果你想通知用户正在运行的任务,你可以执行以下操作:创建QDialog的子类,用QTimer表示WaitDialog一段时间,在对话框构造时启动此计时器,将timeout()信号连接到某些此对话框中的插槽,如果没有正在运行的线程,则接受该对话框:

if (QThreadPool::globalInstance()->activeThreadCount() == 0)
    accept();

然后在MainWindow :: closeEvent:

void MainWindow::closeEvent(QCloseEvent *event) {
    WaitDialog dlg;
    dlg.exec();
    event->accept();
}