2013-12-22 22 views
1

我的問題實際上是,如果我在另一個線程中寫入變量,然後PostMessage到Wnd,UI線程中的GetMessage會與它同步,我可以安全地讀取變量?PostMessage可以在GetMessage之後在UI線程中看到工作線程中變量的變化嗎?

背景是:我想使用PostMessage從後臺線程更新UI,並擔心數據競爭。我需要其他同步實用程序嗎?

謝謝。

編輯: 標題很混亂,所以改變它。

詳述案例: 假設我想更新一個std::string,它是一個全局變量。由於我在PostMessage之前更新了string,我能否安全地閱讀處理該消息的Window Proc中的string

我熟悉C++ 11多線程術語如happens-beforesequence-beforesynchronize-withrelease-acquire概念,所以我的問題可以告訴其他的方式:

是否寫string之前發生的讀?

PS:並且假設這是一次性工作,工作線程不會一次又一次更新string

+1

什麼樣的競爭條件是你關心的?由於您發佈到隊列中,消息將自動按收到的方式排序。 –

+0

@haohaolee,讓我糾正你一點。你不應該擔心數據競賽。在你的情況下,你沒有數據競賽。您應該擔心內存讀取/寫入重新排序。 –

+0

@AlexAntonov如果我正確理解你,你的意思是寫入字符串可以在PostMessage後重新排序,對嗎?但我認爲它必須先於它,因爲它序列 - 在PostMessage之前,所有的副作用都應該發生在字符串 – haohaolee

回答

2

Windows消息隊列是線程安全的生產者 - 消費者隊列。 MSG結構(只有那個)被複制到隊列中,所以一旦消息被髮布,你可以重新加載你自己的消息數據和PostMessage,沒有任何問題。

當開發人員將PostMessage指針/引用設置爲wParam,lParam時,會出現問題。如果指針指向一個本地堆棧對象,則可以在指向它的指針在接收的GetMessage/wndProc中處理之前,將其指定爲RAII-ed。類似的,如果在GetMessage線程中處理之前,在發佈線程中顯式刪除一個指向新實例化對象的指針。

如果您提供更多關於PostMessaging數據的詳細信息,我們應該能夠爲您提供建議。

2

不可以。您對此有零控制。 PostMessage是真正的異步處理,在處理消息時,兩個線程中發生了很多事情(包括處理之前發佈的消息,併發送消息(通過SendMessage)。)

根據你想要做什麼,可能:

  1. 異步傳送DATAS(malloc/new)和PostMessage(指針在wParamlParam)的副本
  2. 同步輸送的指針DATAS與SendMessage
  3. 同步傳輸數據更副本與SendMessageWM_COPYDATA
2

它給你一個保證,就是UI線程將消耗的數據,並能安全地更新窗口。這就是結束的地方,你仍然有另一個線程正在從寫入數據的線程讀取數據,因此需要正常的互鎖以確保UI線程不會讀取更改數據。

這是一個常見的問題,你無法確切地知道 UI線程檢索消息。 UI線程陷入困境可能需要很長時間。因此,除非明確握手,否則無法知道工作線程何時可以繼續更新數據,或者何時可以發佈另一條消息。創建數據的深層副本可解決此問題。或者你需要一個自動重置事件來握手,小心它造成死鎖的能力。

您需要處理的另一種可能的故障模式是PostMessage()可能會失敗。當UI線程由於任何原因而陷入困境時會發生這種情況,只要消息隊列大小超過配額(缺省情況下爲10,000條消息),就會返回FALSE。你可以做些什麼,但睡一會兒再試一次。

當您遇到消防軟管問題時,您還會調用此失敗模式,工作線程以比UI線程更快的速度生成數據。因爲當您使用有限的數據集開始或調試您的程序時很少發生火災,所以消防管理尤其棘手。診斷是WM_PAINT通知丟失,即使UI仍處於活動狀態並且主動處理髮布的消息積壓,您的UI仍會凍結。通過保持在人眼可以感知UI更新的速率之前避免這種情況。當你每秒更新超過25次時,這很好,很慢,這一切都會變成一種難以理解的模糊。

+0

Heh - 我曾經經歷過幾次WMQ重載,通常在涉及到樹視圖控件時,GUI更新非常緩慢。 –

0

PostMessage/GetMessage的文件沒有提供關於synchronize-with關係的任何保證。因此,即使當前/最新版本的Windows在硬件平臺上爲PostMessage/GetMessage提供了synchronize-with關係,但您不應該依賴它,因爲它可以在較新版本的Windows中更改,或者可能無法在其他硬件平臺上使用。所以在這種情況下,IMO必須自己提供synchronize-with的關係,以使您的多線程代碼具有防彈性。例如,您可以使用InterlockedXxx函數(它們既可以獲取也可以釋放語義)或std :: atomic來實現。

+0

的確,文檔與關係同步沒有任何關係,但很難形象化它們不會彼此同步,因爲「GetMessage」看到正確的消息,它應該是一個PostMessage文章 – haohaolee

相關問題