Qt通过QConcurrent :: run终止线程生成 [英] Qt terminate thread spawn by QConcurrent::run

查看:1575
本文介绍了Qt通过QConcurrent :: run终止线程生成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

Say I have few lengthy tasks (read population file, write population file, and run simulation) spawned using QConcurrent::run, as follow:

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

通常,这些任务至少需要15秒才能完成(对于仿真而言,则需要花费多个小时的时间).为了防止尚未完成的线程崩溃,我重新实现了MainWindow :: closeEvent,如下所示:

Usually those tasks take at least 15 seconds to finish (for simulation, it takes more than hours). To prevent crashing from not-yet-finished-threads, I re-implement the MainWindow::closeEvent as follow:

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

这很好,但是当我单击MainWindow的"x"按钮时,尽管它最终终止了该应用程序,但它似乎冻结并显示无响应"(我猜文字是由OS给出的).

This works okay but when I click the 'x' button of MainWindow, it seems freezing and showing 'Not responding' (I guess the text is given by OS), although it finally terminated the app.

我想在MainWindow的close()插槽被触发后立即退出应用程序.因此,如何缩短尚未完成的线程的等待时间?或如何通知用户还有很长的工作正在运行(可能需要几个小时才能完全关闭)? (我尝试将QDialog/QMessagebox包含在closeEvent中,但是新创建的小部件也会冻结)

I want to quit the app as soon as the close() slot of MainWindow is triggered. So, how can I shorten the waiting time for not-yet-finished-threads? Or how can I notify user that there is still a lengthy job running (which can takes hours before completely shut down)? (I tried to include QDialog/QMessagebox in closeEvent but the newly created widgets also freeze)

注意:对于AppClass:lengthyJobs [readPop()/writePop()],它们是独立的函数,我无法细分为更小的步骤.对于AppClass :: runSim(),可能可以执行更小的步骤.

Note: For AppClass:lengthyJobs [readPop() /writePop()], those are self-contained functions and I cannot break downs to smaller steps. For AppClass::runSim(), smaller steps may be possible.

推荐答案

首先,QtConcurrent :: run返回的Future不支持取消.因此,您不能只是取消它.最好的办法是在AppClass中设置一些标志,并在您的longyJobs中检查它(就像您说的那样,对于runSim来说是可能的),然后等待完成.

First of all, the future, returned by QtConcurrent::run doesn't support cancelling. So you can't just cancel it. The best you can do is to set some flag in the AppClass and check it in your lengthyJobs (as you said it is possible in the case of runSim), then wait for completion.

无论哪种方式,如果要向用户通知正在运行的任务,都可以执行以下操作:制作QDialog的子类,例如,将QTimer设置为带有一定时间段的WaitDialog,在对话框构造时启动此计时器,将timeout()信号连接至某些对话框中的插槽,如果没有正在运行的线程,请接受该对话框:

Either way, if you want to notify user of running task, you can do the following: make a subclass of QDialog, say WaitDialog with QTimer with some period, start this timer at dialog construction, connect timeout() signal to some slot in this dialog, and accept the dialog if there's no running thread:

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

,然后在MainWindow :: closeEvent中:

and then in MainWindow::closeEvent:

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

这篇关于Qt通过QConcurrent :: run终止线程生成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆