是CWnd :: GetSafeHwnd()和CWnd :: m_hWnd ThreadSafe?

Ste*_*and 8 c++ winapi multithreading thread-safety thread-local-storage

我面临着大量多线程应用程序的大量崩溃.

阅读这些关于TLS的 MSDN 页面,技术说明本文,我已经了解到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文档说明这是否安全.

arx*_*arx 10

CWnds未映射到HWND; HWND映射到CWnds,这是在每个线程的基础上发生的.CWnd对象不在TLS中(如何工作?)但是每个线程创建临时CWnd对象.

从错误的线程访问临时 CWnd对象绝对是个坏主意(出于Mark Ransom所描述的原因).

但是,如果你有一个永久的CWnd对象(比如你的应用程序的主窗口),那么,一旦创建它,​​从任何线程访问m_hWnd成员都没有问题.它只是内存中永不改变的值.

如果这给您带来麻烦(因为它没有明确记录),那么只需复制HWND并让线程访问它.

PS 这是您用英语链接的文章.


Mar*_*som 5

GetSafeHwnd只是一个包装器,用于检查是否this为NULL,是否为NULL m_hWnd以及是否为NULL 。它不会比m_hWnd它本身具有更多的线程安全性。

当您创建临时CWnd *时,MFC会在它认为安全的位置将其销毁,例如下一次通过消息循环。如果您有多个使用MFC的线程,则您的临时对象在仍在使用时可能会被破坏。您无法从线程执行的任何操作都将检测到此错误。