2013-03-13 99 views
2

平臺:Win7的X64,MinGW的-rubenvb(4.7.2-64),Qt的4.8Qt的終止由QConcurrent線程產卵::運行

說我有一些冗長的任務(讀人羣文件,寫文件的人口,和運行模擬)使用QConcurrent ::運行產生了,如下圖:

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

通常這些任務至少需要15秒完成(仿真,它需要比小時以上)。爲了防止還未完成線程崩潰,我重新實現主窗口::作爲的closeEvent如下:

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

這工作不錯,但,當我點擊主窗口的「X」按鈕,似乎凍結和顯示'沒有響應'(我猜文本是由操作系統給出的),儘管它終於終止了應用程序。

一旦MainWindow的close()插槽被觸發,我想退出應用程序。那麼,我怎樣才能縮短尚未完成線程的等待時間呢?或者我該如何通知用戶仍然有很長的工作正在運行(在完全關閉之前可能需要幾個小時)? (我嘗試在closeEvent中包含QDialog/QMessagebox,但新創建的小部件也凍結)

注意:對於AppClass:lengthyJobs [readPop()/ writePop()],這些是自包含的函數,步驟較小。對於AppClass :: runSim(),更小的步驟可能是可能的。

回答

0

首先,由QtConcurrent :: run返回的未來不支持取消。所以你不能取消它。你可以做的最好的做法是在AppClass中設置一些標誌,並在冗長的作業中檢查它(如你所說在runSim中可能),然後等待完成。無論哪種方式,如果要通知用戶正在運行任務,可以執行以下操作:創建QDialog的子類,用帶有某個句點的QTimer說WaitDialog,在構造對話框時啓動此計時器,將timeout()信號連接到一些槽在此對話框,並接受對話,如果沒有正在運行的線程:

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

,然後在主窗口::的closeEvent:

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

如果我繼承QRunnable /的QThread的任務,是有可能'取消'線程? – 2013-03-13 06:11:27

+0

如果你繼承了QThread,你可以使用QThread :: terminate,儘管文檔說它有潛在危險,因爲運行的線程不會有機會做任何清理。 – user2155932 2013-03-13 06:35:43