2012-02-17 39 views
6

我在一個非常多線程的應用程序中面臨着大量的崩潰。是CWnd :: GetSafeHwnd()和CWnd :: m_hWnd ThreadSafe?

讀取這些MSDN page,technical notethis article on TLS,我已經理解CWnd對象映射到TLS中的HWND,這是一個線程相關的內存訪問。

我打算解開看起來像CWnd線程遠程訪問的所有東西,並將其轉換爲HWND引用,然後使用:: PostMessage作爲通信端口。 (就我目前看到的當前代碼而言,它代表了大量的工作,事實上我精心制定了一個解決方案,這需要很多時間,所以我們不得不討論它)。

但是我的一個同事真的堅持深,我只是保持的CWnd *在外國人線程,採用:: PostMessage的政策好,但使用的CWnd :: GetSafeHwnd()或pMyCWnd-> m_hWnd在國外螺紋以恢復本地HWND。

我一直認爲,無處我已經看到GetSafeHwnd()是線程安全的, 和CWnd的Objet公司在TLS是,它在另一個線程值是不同的。 我錯了? MSDN明確使用術語「意外結果」。

你有什麼看法,從創建者線程的外線程中調用CWnd :: GetSafehwnd()或pMyCWnd-> m_hWnd?

是否有任何MSDN文檔聲明這是安全或不安全的。

回答

7

CWnd沒有映射到HWND; HWND被映射到CWnds,並且這發生在每個線程的基礎上。 CWnd對象不在TLS中(這將如何工作?),但臨時CWnd對象是按每個線程創建的。

從錯誤的線程訪問一個臨時 CWnd對象絕對是一個壞主意(由馬克贖金描述的原因)。然而,如果你有一個永久性的CWnd對象(代表你的應用程序的主窗口),那麼一旦它被創建,從任何線程訪問m_hWnd成員都沒有問題。這只是一個永不改變的內存價值。

如果你遇到麻煩(因爲它沒有明確記錄),然後簡單地使HWND的副本,讓線程訪問。

P.S. Here's the article you linked to英文。

1

如果你有一個多線程應用程序在多個線程都試圖同時訪問HWNDs,它像你有一個設計問題的聲音給我。難道你不能限制你的線程做計算,並處理主線程中的UI問題嗎?這是一個很好的多線程應用程序的典型設計。

+0

不錯的建議,但我不能重新編碼整個事情,很多LOC,它已經超過10年了,有很大的歷史我不能把它抹去:-) – 2012-02-17 16:52:07

+0

那麼,你的問題基本上是「我必須做這件極不安全的事情,安全嗎?「答案可能是「沒有東西會使它安全」。您可以在某種程度上使其更安全*,但我懷疑它可以在當前的設計中無碰撞。 – StilesCrisis 2012-02-17 16:56:49

+0

(順便說一下,我可以聯繫,我也在一個10歲的MFC代碼庫上工作,感謝上帝,我們沒有線程,原來的編程人員幾乎沒有足夠的智能來獲得這個權利) – StilesCrisis 2012-02-17 16:57:39

4

GetSafeHwnd只是一個包裝,它檢查this是否爲NULL,如果不是則返回m_hWnd,如果是,則返回NULL。它不會比m_hWnd本身更具線程安全性。

當你創建一個臨時的CWnd *,MFC會在它認爲安全的,這一點摧毀它,例如下一次通過的消息循環。如果您有多個使用MFC的線程,那麼當您仍在使用它時,您的臨時對象可能會被破壞。你可以從你的線程中做什麼都不會檢測到這個錯誤。

+0

都是CWnd *臨時或不是?我的意思是在創建窗口時在創建者線程中創建的一個CWnd *,它是否也是暫時的? (我的意思不是通過CWnd :: FromHandle()計算出來的) – 2012-02-17 17:13:38