我面临着大量多线程应用程序的大量崩溃。
阅读这些MSDN page,technical note和this article on TLS,我了解到CWnd
个对象被映射到线程本地Storgae中的HWND(TLS,这是一个线程依赖性内存访问)。
我打算将看起来像CWnd线程远程访问的所有内容分离,并将其转换为HWND
引用,然后使用::PostMessage
作为通信端口。
但是我的一位同事真的坚持认为我只是将CWnd*
保留在外国人话题中,采用::PostMessage
政策确定,但使用CWnd::GetSafeHwnd()
或pMyCWnd->m_hWnd
外部线程,以便恢复本机HWND
。
我一直在争论无处我看到GetSafeHwnd()
是线程安全的,并且CWnd
对象在TLS中,它在另一个线程中的值是不同的
我错了? MSDN显然使用了术语意外结果。
关于在创建者线程中调用外部线程中的CWnd::GetSafehwnd()
或pMyCWnd->m_hWnd
,您的观点是什么?
您是否有任何MSDN文档说明这是否安全。
答案 0 :(得分:10)
CWnds未映射到HWND; HWND映射到CWnds,这是在每个线程的基础上发生的。 CWnd对象不在TLS中(如何工作?)但每个线程创建临时CWnd对象。
从错误的线程访问临时 CWnd对象绝对是一个坏主意(出于Mark Ransom所描述的原因)。
但是,如果你有一个永久的CWnd对象(比如你的应用程序的主窗口),那么,一旦创建它,从任何线程访问m_hWnd成员都没有问题。它只是内存中永远不会改变的值。
如果这给您带来麻烦(因为它没有明确记录),那么只需复制一份HWND并让线程访问它。
P.S。 Here's the article you linked to英文版。
答案 1 :(得分:5)
GetSafeHwnd只是一个包装器,用于检查this
是否为NULL,如果不是则返回m_hWnd
,如果是,则返回NULL。它不会比m_hWnd
本身更加线程安全。
当您创建临时CWnd *时,MFC将在其认为安全的位置销毁它,例如下一次通过消息循环。如果你有多个线程使用MFC,那么你的临时对象可能会在你仍在使用时被销毁。您可以从线程中执行任何操作都无法检测到此错误。
答案 2 :(得分:1)
如果你有一个多线程应用程序,其中多个线程都试图一次访问HWND,听起来像你有一个设计问题。你不能限制你的线程进行计算,并处理主线程上的UI问题吗?这是一个优秀的多线程应用程序的典型设计。