2012-02-17 29 views
6

我在一个非常多线程的应用程序中面临着大量的崩溃。是CWnd :: GetSafeHwnd()和CWnd :: m_hWnd ThreadSafe?

读取这些MSDN page,technical notethis article on TLS,我已经理解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文档声明这是安全或不安全的。

回答

7

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

从错误的线程访问一个临时 CWnd对象绝对是一个坏主意(由马克赎金描述的原因)。然而,如果你有一个永久性的CWnd对象(代表你的应用程序的主窗口),那么一旦它被创建,从任何线程访问m_hWnd成员都没有问题。这只是一个永不改变的内存价值。

如果你遇到麻烦(因为它没有明确记录),然后简单地使HWND的副本,让线程访问。

P.S. Here's the article you linked to英文。

1

如果你有一个多线程应用程序在多个线程都试图同时访问HWNDs,它像你有一个设计问题的声音给我。难道你不能限制你的线程做计算,并处理主线程中的UI问题吗?这是一个很好的多线程应用程序的典型设计。

+0

不错的建议,但我不能重新编码整个事情,很多LOC,它已经超过10年了,有很大的历史我不能把它抹去:-) – 2012-02-17 16:52:07

+0

那么,你的问题基本上是“我必须做这件极不安全的事情,安全吗?“答案可能是“没有东西会使它安全”。您可以在某种程度上使其更安全*,但我怀疑它可以在当前的设计中无碰撞。 – StilesCrisis 2012-02-17 16:56:49

+0

(顺便说一下,我可以联系,我也在一个10岁的MFC代码库上工作,感谢上帝,我们没有线程,原来的编程人员几乎没有足够的智能来获得这个权利) – StilesCrisis 2012-02-17 16:57:39

4

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

当你创建一个临时的CWnd *,MFC会在它认为安全的,这一点摧毁它,例如下一次通过的消息循环。如果您有多个使用MFC的线程,那么当您仍在使用它时,您的临时对象可能会被破坏。你可以从你的线程中做什么都不会检测到这个错误。

+0

都是CWnd *临时或不是?我的意思是在创建窗口时在创建者线程中创建的一个CWnd *,它是否也是暂时的? (我的意思不是通过CWnd :: FromHandle()计算出来的) – 2012-02-17 17:13:38