2014-01-22 58 views
0

我想在事件中取消QtConcurent :: map計算。取消QtConcurent計算

這是我的測試代碼(該計算是由一個無限循環來表示):

class Test : public QObject 
{ 
    Q_OBJECT 

public: 
    Test(QObject *parent=0) : QObject(parent){} 

    void test() 
    { 
     qDebug() << tr("thread:") << QThread::currentThread(); 

     //computation 
     while(true); 
    } 
}; 

我測試的名單,和我做的:

//QFuture<void> m_concurentResult; 
m_concurentResult = QtConcurrent::map(m_collection, &Test::test); 
//That's Ok, I have the two outputs : 
// QThread(0x4e21f8, name = "Thread (pooled)") 
// QThread(0x4e21b8, name = "Thread (pooled)") 

的目標是取消當用戶點擊一個按鈕時的所有計算。

void Widget::on_pushButton_clicked() 
{ 
    m_concurentResult.cancel(); 
    m_concurentResult.waitForFinished(); 
} 

但是,當我點擊按鈕,UI被凍結,什麼也沒有完成。感謝幫助 !

回答

0

正如Peppe所說,QTConcurrent只會取消進一步處理(如果您對序列進行映射或過濾)。一件物品不能被打斷。

這是因爲線程一般不能被取消或中斷。

在C++中,您需要自己管理它。 (關於如何擴展C++,可以通過將異常推送到某個線程來拋出異常,但是細節太多而無法進入標準。)

對於某些運行的語言一個VM(Java,Python)在該線程正在執行Java/Python代碼時是可行的,但是當鎖定在內核/本機)時是可行的。因此,while(true)應該是while(!m_interrupted)

+0

好的,我在類Test上有「volatil bool m_interrupted」。我添加了一個public void void interrupt(),它使m_interrupted變爲true。 從主線程中,我將信號連接到集合中的所有對象Test的插槽。我應該有直接,排隊還是自動連接? 插槽是在主線程還是在線程池中執行的?謝謝 ! – saad

+0

@saad:編輯你的問題。顯示新的代碼。並閱讀有關插槽連接的文檔。這取決於qobject屬於哪個線程,因爲它是從線程中運行的事件回發中發送的插槽連接。 – Macke

1

除了我會檢查cancel是否實際上做了某些事情(也就是說,如果它沒有實現,我不會感到驚訝),您錯過了它的要點:它不會取消任務目前正在運行,但是它阻止進一步的任務被安排用於該計算。因此,如果您正在運行10個項目(1 .. 10)的地圖,並且項目1和2正在處理中,並且您調用取消,則將繼續執行1和2上的計算;可能沒有更多的項目將被處理(但你沒有得到任何保證)。

一般來說,問題是您無法輕鬆取消線程。例如,Qt不支持QThreads。