8

我在一个高度多线程的应用程序上面临许多崩溃。

阅读这些 MSDN页面技术说明这篇关于 TLS的文章,我了解到CWnd对象在 Thread Local Storgae(TLS,这是一个线程相关的内存访问)中映射到 HWND。

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

但是我的一位同事确实坚持我只是保留CWnd*在外国线程中,采用::PostMessage策略可以,但是在外国线程中使用CWnd::GetSafeHwnd()orpMyCWnd->m_hWnd以便恢复本地HWND

我一直在争辩说,我在任何地方都没有看到它GetSafeHwnd()是线程安全的,并且CWnd对象在 TLS 中,它在另一个线程中的值是不同的。

我错了 ?MSDN 显然使用了Unexpected results一词。

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

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

4

3 回答 3

10

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

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

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

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

PS这是你链接到的英文文章。

于 2012-02-17T17:18:46.927 回答
5

GetSafeHwnd is simply a wrapper that checks if this is NULL, returns m_hWnd if not and NULL if it is. It won't be any more threadsafe than m_hWnd itself.

When you create a temporary CWnd*, MFC will destroy it at a point it considers safe, such as the next pass through the message loop. If you have multiple threads using MFC then your temporary object could get destroyed while you're still using it. Nothing you can do from your thread will detect this error.

于 2012-02-17T16:57:53.310 回答
1

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

于 2012-02-17T16:49:35.040 回答