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

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

本文关键字:CWnd hWnd ThreadSafe GetSafeHwnd Is and      更新时间:2023-10-16

我在一个多线程应用程序上遇到了许多崩溃。

阅读这些MSDN页面、技术说明和这篇关于TLS的文章,我了解到CWnd对象被映射到线程本地Storgae(TLS,这是一种依赖于线程的内存访问)中的HWND。

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

但我的一位同事真的坚持认为,我只需要在外部线程中保留CWnd*,采用::PostMessage策略就可以了,但在外部线程使用CWnd::GetSafeHwnd()pMyCWnd->m_hWnd,以便恢复本地HWND

我一直在争论where我已经看到GetSafeHwnd()是线程安全的,而CWnd对象在TLS中,它在另一个线程中的值是不同的。

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

关于从创建者线程在外线程中调用CWnd::GetSafehwnd()pMyCWnd->m_hWnd,您的观点是什么?

你有没有MSDN文档说明这是否安全。

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

从错误的线程访问临时CWnd对象肯定是个坏主意(原因由Mark Ransom描述)。

然而,如果你有一个永久的CWnd对象(比如说,代表你的应用程序的主窗口),那么一旦创建了它,从任何线程访问m_hWnd成员都不会有任何问题。这只是记忆中的一个永远不会改变的价值。

如果这让您感到困扰(因为它没有明确记录),那么只需制作HWND的副本,并让线程访问它。

附言:这是你链接到的英文文章。

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

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

如果您有一个多线程应用程序,其中多个线程都试图同时访问HWND,那么在我看来,您似乎有设计问题。难道不能将线程限制在计算上,并在主线程上处理UI问题吗?这是一个好的多线程应用程序的典型设计。