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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了是CWnd :: GetSafeHwnd()和CWnd :: m_hWnd ThreadSafe?相关的知识,希望对你有一定的参考价值。

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

阅读这些MSDN pagetechnical notethis article on TLS,我已经了解到CWnd对象被映射到Thread Local Storgae中的HWND(TLS,这是一个线程依赖的内存访问)。

我打算将看起来像CWnd线程远程访问的所有内容分离,并将其转换为HWND引用,然后使用::PostMessage作为通信端口。

但是我的一位同事真的坚持认为我只是将CWnd*保留在外国人的线程中,采用::PostMessage政策确定,但在外国线程中使用CWnd::GetSafeHwnd()pMyCWnd->m_hWnd以便恢复原生的HWND

我一直在争论说,我没有看到GetSafeHwnd()是线程安全的,并且CWnd objet在TLS中,它在另一个线程中的价值是不同的。

我错了 ? MSDN显然使用了术语“意外结果”。

你有什么观点,关于从创建者线程中调用外部线程中的CWnd::GetSafehwnd()pMyCWnd->m_hWnd

您是否有任何MSDN文档说明这是否安全。

答案

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

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

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

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

附: Here's the article you linked to英文。

另一答案

GetSafeHwnd只是一个包装器,用于检查this是否为NULL,如果不是则返回m_hWnd,如果是,则返回NULL。它不会比m_hWnd本身更安全。

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

另一答案

如果你有一个多线程应用程序,其中多个线程都试图一次访问HWND,听起来像你有一个设计问题。你不能限制你的线程进行计算,并处理主线程上的UI问题吗?这是一个优秀的多线程应用程序的典型设计。

以上是关于是CWnd :: GetSafeHwnd()和CWnd :: m_hWnd ThreadSafe?的主要内容,如果未能解决你的问题,请参考以下文章

GetSafeHwnd

HWND CWnd 等的互相转换

无法在 MFC 无窗口 Activex 中获取 Cwnd 类的句柄?

VC遍历窗口上的控件

SendMessage模拟点击按钮的问题

MFC-GetClientRect获取窗口客户区的坐标