I am facing numerous crashes on a application which is heavily multi-threaded.
Reading these MSDN page, technical note and this article on TLS, I have understood that CWnd
objects are mapped to HWND in the Thread Local Storgae (TLS, which is a thread dependendent memory access).
I was going to decouple everything that looks like CWnd thread-remote access, and transform it into HWND
references and then use ::PostMessage
as communication port.
But one of my colleagues really insisted that I just keep the CWnd*
in the foreigner threads, adopt the ::PostMessage
policy ok, but use CWnd::GetSafeHwnd()
or the pMyCWnd->m_hWnd
in the foreign threads so as to recover the native HWND
.
I have been arguing that nowhere I have seen that the GetSafeHwnd()
is threadsafe, and that the CWnd
objet being in the TLS, it's value in another thread is different.
I am wrong ? The MSDN is clearly using the term Unexpected results.
What's your point of view, about calling CWnd::GetSafehwnd()
or pMyCWnd->m_hWnd
in outer threads from the creator thread ?
Do you have any MSDN documentation that states that this is safe or not.
CWnds are not mapped to HWNDs; HWNDs are mapped to CWnds, and this happens on a per-thread basis. The CWnd object is not in TLS (how would that work?) but temporary CWnd objects are created per-thread.
Accessing a temporary CWnd object from the wrong thread is definitely a bad idea (for the reasons described by Mark Ransom).
However, if you have a permanent CWnd object (representing the main window of your app, say) then, once it is created, there is no problem at all in accessing the m_hWnd member from any thread. It's just a value in memory that never changes.
If this troubles you (because it's not explicitly documented) then simply make a copy of the HWND and let the threads access that.
P.S. Here's the article you linked to in English.