2011-11-04 74 views
1

我目前正在開發一個使用Qt進行原始視頻數據回放的多線程應用程序。有三個工作線程。一個是Reader線程,一個是處理器線程,另一個是視頻輸出線程。讀取器線程將原始數據讀入緩衝區,然後處理器將處理原始數據並將可顯示的數據放入幀FIFO中。陷入循環等待狀態。需要幫助退出

我的原始數據緩衝區實現爲一個哈希表,這意味着每個幀索引將有其相應的原始數據。一旦處理器完成處理原始數據一個特定幀,它將從原始數據緩衝區中刪除原始數據,以便讀取器可以在數據返回到之前讀取的幀後將數據讀入緩衝區。

我現在執行暫停功能時出現問題。我想要做的是當視頻暫停時,處理器和閱讀器應該退出,並且視頻輸出線程將在fifo中顯示一個相同的幀。我現在可以正確退出處理器線程。讀者似乎陷入了一個循環的等待狀況。

下面是我的讀者線程的一些代碼。

void ReaderThread::run() 
    { 
     forever 
     { 
     //inputState_ is internal state of the reader 
     if (inputState_ == stop) 
      // return from run() if state is stop 
      return;    
     //dataBuffer is a pointer to raw data buffer object 
     //This grab the mutex lock of the raw data buffer 
     dataBuffer->lock() 
     //frameIndex is counter for frame 
     if (dataBuffer->contains(frameIndex_)) 
     { 
      //mutex_ is a member variable of type QMutex 
      mutex_.lock(); 
      //Wait for the data to be removed. 
      dataBuffer->waitForWritable(); 
      mutex_.unlock(); 
     } 
     dataBuffer->unlock(); 

     // Read data to raw frame buffer 
     uchar rawDataPointer = readRawData(); 

     dataBuffer->lock(); 
     //insert the frame number and corresponding pointer into the hash table 
     dataBuffer->insert(frameIndex, rawDataPointer); 
     //wake up processor. 
     dataBuffer->wakeForReadable() 
     dataBuffer->unlock(); 

     mutex_.lock(); 
     if (inputState_ == play) 
      frameIndex++; 
     mutex_.unlock(); 
     } 
    } 

    void ReaderThread::stop() 
    { 
     mutex_.lock(); 
     inputState_ = stop; 
     //Wake up the reader if the reader is waiting 
     dataBuffer->wakeAllWritable(); 
     mutex_.unlock(); 

     // Wait for run() to return. 
     QThread::wait(); 
    } 

處理器線程的實現方式類似。我一開始就停止了處理器,並且成功了。當我想從run()返回時,我從主線程調用ReaderThread :: stop()。但是我陷入了一個循環的等待狀態,如果讀者線程在緩衝區等待寫入,它永遠不會解鎖這個讀者線程的mutex_。因此,停止將總是阻止,程序只是掛起。我試圖在dataBuffer-> waitForWritable()之前不鎖定mutex_,但是,在調用dataBuffer-> wakeAllWritable()後,讀者線程將等待可寫權限。

任何人都可以提出一種方法來解決這個問題?我一直在努力想弄清楚如何擺脫這種循環等待的情況,但並沒有完全解決,因爲我對線程化編程還很陌生。

+0

不應該在調用wakeAllWritable()之前鎖定dataBuffer嗎?這樣你就可以從waitForWritable和wakeForWritable中刪除_mutex.lock。現在讓我知道它是如何發展的。 –

+0

@Franco,這是有道理的。當我回到辦公室時,我會試試看。謝謝。 – Scrathis

回答

1

我想你在停止()使用它,就像在此之前應該鎖定的DataBuffer:以這種方式

void ReaderThread::stop() 
    { 
     mutex_.lock(); 
     inputState_ = stop; 
     mutex_.unlock(); 
     //Wake up the reader if the reader is waiting 
     dataBuffer->lock(); 
     dataBuffer->wakeAllWritable(); 
     dataBuffer->unlock();    

     // Wait for run() to return. 
     QThread::wait(); 
    } 

你可以刪除mutex_.lock()的另一種方法&解鎖:

//dataBuffer is a pointer to raw data buffer object 
    //This grab the mutex lock of the raw data buffer 
    dataBuffer->lock() 
    //frameIndex is counter for frame 
    if (dataBuffer->contains(frameIndex_)) 
    { 
     dataBuffer->waitForWritable(); 
    } 
    dataBuffer->unlock(); 
+0

是的,我試過了。它工作正常,我不需要很多成員互斥體的線程。這似乎是一個微不足道的因爲我沒有完全理解QWaitCondition的機制。非常感謝@Franco。 – Scrathis

+0

不客氣。 –