2015-11-05 171 views
1

我使用一個std :: condition_variable這樣:執行了等待一個std :: condition_variable在「等待回調」通知

void wait() 
{ 
    std::unique_lock<std::mutex> lock(m_stateCompletedMutex); 

    m_waitCondition.wait(lock, [this](){return (m_state == STATE_COMPLETED);}); 
} 

我與此很高興,但現在我想在「等待期間」執行一些代碼(我不知道是否可以這樣說,但這是想法),例如更新GUI或增加等待計數器或其他任何東西。

說我們使用Qt,我已經試過這樣的事情:

void wait() 
{ 
    std::unique_lock<std::mutex> lock(m_stateCompletedMutex); 

    while (m_state != STATE_COMPLETED) 
    { 
     m_waitCondition.wait(lock); 

     // Use this an example, it could be any code, executed in the waiting thread 
     qApp->processEvents(QEventLoop::ExcludeUserInputEvents); 
    } 
} 

這裏的目標是保持GUI響應(至少對系統事件,沒有用戶輸入),而我們正在等待爲了完成工作線程。

我對這個代碼的兩個問題:

1 /這是不是好辦法做到這一點,還是有更好的方法來執行代碼「在等待」

2 /執行多久「等待代碼」(在我的例子中的qApp-> processEvents調用)?它依賴於系統嗎?還是取決於當前的CPU負載或其他?或者我應該使用m_waitCondition。 wait_for確保最低頻率呼叫?

關於第2點/,我已經測試過監視它(使用std :: chrono :: high_resolution_clock),延遲似乎在我的應用程序中的200ms到4000ms之間,我認爲這是一個很大的範圍。

+0

對於等待時執行代碼,您需要創建新的線程或進程。設計可以有10個線程,其中9個在給定時刻等待。通常'.wait()'只在對應的'.notify'調用之後纔會返回。 *虛假喚醒*實際上很少見。 – Tsyvarev

+0

「虛假喚醒實際上很少見」:我也在想。但是我已經用一個經過時間計數器測試了一個輸出到控制檯(而不是我的例子中的qApp-> processEvents調用),並且消息每隔200ms到4000ms寫入控制檯。 – Aurelien

+0

也就是說,你的'.wait()'喚醒**只有虛假的**(沒有在其他線程中調用'.notify()')每200-4000毫秒? – Tsyvarev

回答

0

1 /這是不是好辦法做到這一點,還是有更好的方法來執行代碼「在等待」

至於我的「好辦法」做這將是隱藏的細節計算架構的GUI部分。例如接口可以是這樣的:

extern void calc_something(Params, const std::function<void()> &end_calc_callback); 

其中end_calc_callback可以在另一個(非GUI)線程上下文來調用。

所以使用會是這樣

std::atomic<bool> result_ready{false}; 
calc_something(Params(), [&result_ready]() { result_ready = true; }); 
//wait result_ready 

2 /多久執行了 「等待代碼」(即qApp-> processEvents叫我>爲例)?它依賴於系統嗎?

您可以設置最大工作時間爲QCoreApplication::processEvents,看到這個Qt文檔,多久你設置超時時間取決於您的代碼和用戶, 比如讓你有這樣的代碼:

std::atomic<bool> result_ready{false}; 
calc_something(Params(), [&result_ready]() { result_ready = true; }); 
ProgressWindow pw; 
pw.show(); 
while (!result_ready) 
    qApp->processEvents(QEventLoop::ExcludeUserInputEvents, timeout); 

讓我們假設你已經在ProgressWindow定時器中畫出了一些動畫, 人可以響應屏幕上的某些東西讓我們說200ms(https://en.wikipedia.org/wiki/Mental_chronometry)然後取決於你在ProgressWindow中顯示的動畫 ,以及用戶反應可以選擇超時。

+0

謝謝,但關於第2點,我知道可以使用超時參數調用processEvents。我的問題不是這個代碼被調用多長時間,而是多頻繁。我的意思是,即使不是「processEvents」,兩次調用之間的延遲是多少。在我的情況下,每次調用之間都會看到200ms-4000ms的延遲,即使調用只是一個控制檯消息(而不是processEvent調用)。這個延遲是如何驅動的? – Aurelien

+0

叫什麼多久?多久工作'processEvents'? – fghj

+0

怎麼**頻繁**,不要多久。在我的情況下,我看到**每次調用之間200ms-4000ms的延遲**,即使這個調用只是一個控制檯(不是processEvent調用)的消息。這個延遲是如何驅動的? – Aurelien

1

不,這不是正確的做法。您絕對不能在Qt(或任何事件驅動的框架)中的Main(GUI)線程上等待或休眠。

與其等待,GUI線程必須接收某種事件。如果一切都是Qt(即不是一些不能被Qt-isms「污染」的外部代碼),那麼在完成時只需讓另一個線程發出一個信號。

否則,您可以採取user1034749的方法,並將回調傳遞給計算函數。這個回調反過來可以設置一個標誌,或者堅持使用Qt的事件驅動特性,發出一個信號,沿着你的GUI進行下一步(即顯示計算結果)。

很可能是,如果您打電話給ProcessEvents()你做錯了