2013-03-19 76 views
0

我已經線程迭代生成一些幾何。我使用VTK進行渲染。每次迭代後,我想顯示(呈現)當前的進度。我的方法按預期工作,直到最後2個線程仍在等待QWaitCondition。即使它們在QWaitCondition隊列中的狀態爲wokenUp(通過調試器檢查),它們也會被阻止。我懷疑有2個線程的數量以某種方式與我的處理器的4個內核連接。2個線程仍然掛在QWaitCondition上,儘管全部調用

簡化代碼如下。我做錯了什麼,以及如何解決它?

class Logic 
{ 
    QMutex threadLock, renderLock; 
    //SOLUTION: renderLock should be per thread, not global like this! 
    QWaitCondition wc; 
    bool render; 
    ... 
} 

Logic::Logic() 
{ 
    ... 
    renderLock.lock(); //needs to be locked for QWaitCondition 
} 

void Logic::timerProc() 
{ 
    static int count=0; 
    if (render||count>10) //render wanted or not rendered in a while 
    { 
     threadLock.lock(); 
     vtkRenderWindow->Render(); 
     render=false; 
     count=0; 
     wc.wakeAll(); 
     threadLock.unlock(); 
    } 
    else 
     count++; 
} 

double Logic::makeMesh(int meshIndex) 
{ 
    while (notFinished) 
    { 
     ...(calculate g) 
     threadLock.lock(); //lock scene 
     mesh[meshIndex]->setGeometry(g); 
     render=true; 
     threadLock.unlock(); 
     wc.wait(&renderLock); //wait until rendered 
    } 
    return g.size; 
} 

void Logic::makeAllMeshes() 
{ 
    vector<QFuture<double>> r; 
    for (int i=0; i<meshes.size(); i++) 
    {  
     QFuture<double> future = QtConcurrent::run<double>(this, &Logic::makeMesh, i); 
     r.push_back(future); 
    } 

    while(any r is not finished) 
     QApplication::processEvents(); //give timer a chance 
} 
+1

您必須呼叫等待鎖定互斥! – 2013-03-19 11:10:26

+0

我這樣做:wc.wait(&renderLock);還是需要一些額外的電話? – 2013-03-19 11:38:16

回答

0

問題是我需要每個線程使用一個QMutex,而不僅僅是一個全局QMutex。正確的代碼如下。感謝您的幫助UmNyobe!

class Logic 
{ 
    QMutex threadLock; 
    QWaitCondition wc; 
    bool render; 
    ... 
} 

//nothing in constructor related to threading 

void Logic::timerProc() 
{ 
    //count was a debugging workaround and is not needed 
    if (render) 
    { 
     threadLock.lock(); 
     vtkRenderWindow->Render(); 
     render=false; 
     wc.wakeAll(); 
     threadLock.unlock(); 
    } 
} 

double Logic::makeMesh(int meshIndex) 
{ 
    QMutex renderLock; //fix 
    renderLock.lock(); //fix 
    while (notFinished) 
    { 
     ...(calculate g) 
     threadLock.lock(); //lock scene 
     mesh[meshIndex]->setGeometry(g); 
     render=true; 
     threadLock.unlock(); 
     wc.wait(&renderLock); //wait until rendered 
    } 
    return g.size; 
} 

void Logic::makeAllMeshes() 
{ 
    vector<QFuture<double>> r; 
    for (int i=0; i<meshes.size(); i++) 
    {  
     QFuture<double> future = QtConcurrent::run<double>(this, &Logic::makeMesh, i); 
     r.push_back(future); 
    } 

    while(any r is not finished) 
     QApplication::processEvents(); //give timer a chance 
} 
2

您的代碼至少有一個缺陷。 countrender屬於關鍵部分,這意味着他們需要被保護以防止併發訪問。

假設有更多的線程在wc.wait(&renderLock);上等待。有人執行wc.wakeAll();。所有線程都被喚醒。假設至少一個線程看到notFinished爲真(如果你的任何代碼的意義,這必須是可能的),並返回到執行:

threadLock.lock(); //lock scene 
    mesh[meshIndex]->setGeometry(g); 
    render=true; 
    threadLock.unlock(); 
    wc.wait(&renderLock) <----OOPS... 

線程回來。第二次,他不沒有鎖renderLock。所以卡米爾Klimek是正確的:你打電話等一個互斥你沒有舉行

您應該刪除構造函數中的鎖,並在調用條件之前鎖定。無論您鎖定renderlock,該線程都不應該包含threadlock

+0

count是解鎖線程的解決方法,並且不會併發訪問 - 只有主線程才能訪問它。 但我按照你的建議做了,沒有區別。 – 2013-03-20 08:15:14

+0

請更新代碼。 – UmNyobe 2013-03-20 14:15:24

+0

您是否再次閱讀我的答案? – UmNyobe 2013-03-20 15:37:35

相關問題