2013-07-16 27 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