2013-07-16 25 views
1

我有一個問題與qt同步多個線程(不幸的是3.3.8)。因爲啓動一個線程是一項耗時的任務,我想啓動一個(工作)線程一次,將其保存在其運行方法中,並通知它新的工作。但是我還需要在所有工作完成時同步調用線程中的這些工作線程。等待多個正在運行的線程通過waitconditions

我知道的QThread超載不正確的使用它,但使用Qt 3.3.8沒有moveToThread法,所以我不得不這樣做。

的工作線程級被定義如下(簡化的)

class WorkerThread : public QThread 
{ 
    private: 
    QWaitCondition m_wcNewWork; 
    QMutex m_mutexStopped; 
    bool m_bStopped; /// Stop thread execution 

    void run() 
    { 
     m_mutexStopped.lock(); 
     while(!m_bStopped) 
     { 
      m_mutexStopped.unlock();  
      m_wcNewWork.wait(); //wait for new work 

      msleep(1000); // do something 

      //>notify main thread that the work is done< 

      m_mutexStopped.lock(); 
     } 
     m_mutexStopped.unlock();  
    } 
    public: 
    WorkerThread() : m_bStopped(false) {} 
    ~WorkerThread() 
    { 
     m_mutexStopped.lock(); 
     m_bStopped = true; 
     m_mutexStopped.unlock();  
     wait(); // Wait for thread 

     //Cleanup  
    } 
    void startProcessing() 
    { 
     m_wcNewWork.wakeOne(); /// Wakeup thread, since there is something to do   
    }   
} 

那些工作線程的一束在另一個線程創建的。我們稱之爲MainThread。 現在我需要通知MainThread所有工作線程都完成了工作。我認爲MainThread中的WaitConditions可以解決這個問題,每個WorkerThread都有一個解決這個問題的可能性。然後在MainThread我寫的東西像

QWaitCondition waitWorkDone[numWorker]; 

//Start working 
for (int i = 0; i < numWorker; i++) 
{ 
    WorkerThread[i].setWaitCondition(waitWorkDone); 
    WorkerThread[i].startProcessing(); 
} 

//Wait for all workers to finish their work 
for (int i = 0; i < numWorker; i++) 
{ 
    waitWorkDone[i].wait(); 
} 

在的WorkerThread ::運行方法我用一個waitWorkDone.wakeOne()通知MainThread,這項工作已經完成。不幸的是,這是行不通的。當waitWorkDone在等待之前被喚醒時,MainThread會一直等待。

所以問題是:我如何同步線程,不離開他們的運行方法?我認爲,在Qt的4我可以使用線程池來做到這一點,但他們不存在的Qt提前3

感謝。

回答

0

似乎您正在以錯誤的方式使用您的條件變量(QWaitCondition)。他們需要使用互斥體才能正常工作,否則會喚醒......電話可能會丟失,就像這裏一樣。 你可以修復它們,或者(更簡單的方法)只使用信號燈等待工作人員;工作線程每增加一次,主線程減少它的numWorker次數。

你可以看看有關「並行線程入門」一書的條件變量更好的解釋(非常好介紹的多線程,雖然有點亂日期)

+0

謝謝你的書提示。我會看看它。我也有關於waitcondition :: wait-method中的互斥量的想法,但我對此感到困惑。如果互斥體是強制性的,那麼沒有互斥體的等待的目的是什麼? – AquilaRapax

+0

條件變量和相應的互斥鎖應該一起工作。當沒有人正在等待相應的條件變量(這就是爲什麼wait ...函數接受互斥體)時,互斥鎖應該被鎖定,並且當您調用喚醒條件變量時,沒有人等待它可能會丟失(實際發生)。 – 2013-07-16 11:32:38