平台: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(),可能会采用较小的步骤。
答案 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();
}