Is CWnd::GetSafeHwnd() and CWnd::m_hWnd ThreadSafe?

Stephane Rolland picture Stephane Rolland · Feb 17, 2012 · Viewed 8.4k times · Source

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.

Answer

arx picture arx · Feb 17, 2012

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.