MFC关于多线程中传递窗口类指针时ASSERT_VALID出错的另类解决 转
2017-05-08 15:54
288 查看
MFC关于多线程中传递窗口类指针时ASSERT_VALID出错的另类解决
在多线程设计中,许多人为了省事,会将对话框类或其它类的指针传给工作线程,而在工作线程中调用该类的成员函数或成员变量等等。
但是在Debug版本时,在某些情况下,特别是在工作线程中调用pWnd->UpdateData(FALSE)时,会出现错误。这个错误的原因网上有许多地方讲到了,但是,令人失望的是,讲得好的没几篇,都是非要讲什么线程模块状态什么的,让人看得云里雾里(不过,说实话,也就是从这些文章中才知道是怎么回事的)。
其实本人以为,说穿了,很简单,避免多线程冲突,下面举例说明:
在你的对话框类中有一编辑框和一按钮,编辑框关联了变量为m_strText
现在在你按下按钮时,你有代码如下:
m_strText = "Hello";
UpdateData(FALSE);
在正常情况下你的编辑框中很显然会显示出"Hello"来。
但是,不怕一万,就怕万一,偏偏在你m_strText="Hello"这个代码执行之后,你的线程切换了,可是在你的工作线程里,你却将m_strText设置成了"Sorry",结果当线程切换回来后,UpdateData(FALSE)后,编辑框上就变成"Sorry"而不是"Hello"了。
所以,MFC并不建议这种多线程中传递MFC对象的指针,而且MFC人为的加了一个ASSERT_VALID来表示它们的不建议。
但是,不建议并不表示不能用,如果你能够确认你的线程不会互相冲突,你就大胆的用吧。
正因为如此,MFC只是在Debug版本中才有这个ASSERT_VALID的问题存在,在Release版本中却没有,因为它没有理由来阻止我们用。
虽然如此,但是毕竟我们的调试许多时候是要用到Debug版本的,MFC的如此做法还是给我们带来了诸多不变,幸运的是,MFC将它的真正检测线程相关MFC对象的代码做成了虚拟函数,也就是说,我们可以重载它,这样在Debug时,也不会出这问题了。
下面,让我们热烈欢迎我们今天的主角出场--virtual void CObject::AssertValid( ) const;
ASSERT_VALID最后会调用MFC类对象的AssertValid函数,因此只要重载AssertValid,令其不检测与线程相关的这些东东,就不会弹出出错框了(其实这些出错框,本来就是人为的弹出来的)。
费话就不说了,假设我们的对话框是CTmthDlg,下面是重载后的代码
void CTmthDlg::AssertValid() const
{
if (m_hWnd == NULL)
return; // null (unattached) windows are valid
// check for special wnd??? values
ASSERT(HWND_TOP == NULL); // same as desktop
if (m_hWnd == HWND_BOTTOM)
ASSERT(this == &CWnd::wndBottom);
else if (m_hWnd == HWND_TOPMOST)
ASSERT(this == &CWnd::wndTopMost);
else if (m_hWnd == HWND_NOTOPMOST)
ASSERT(this == &CWnd::wndNoTopMost);
else
{
// should be a normal window
ASSERT(::IsWindow(m_hWnd));
// should also be in the permanent or temporary handle map
// Note: if either of the above asserts fire and you are
// writing a multithreaded application, it is likely that
// you have passed a C++ object from one thread to another
// and have used that object in a way that was not intended.
// (only simple inline wrapper functions should be used)
//
// In general, CWnd objects should be passed by HWND from
// one thread to another. The receiving thread can wrap
// the HWND with a CWnd object by using CWnd::FromHandle.
//
// It is dangerous to pass C++ objects from one thread to
// another, unless the objects are designed to be used in
// such a manner.
}
}
这里我只是简单的从CWnd::AssertValid中拷贝来,然后注释掉检测线程中MFC对象和Windows对象映射的代码。
另外,请注意一下MFC自己的一些注释。
// It is dangerous to pass C++ objects from one thread to
// another, unless the objects are designed to be used in
// such a manner.
现在,请在你的工作线程中调用
((CTmthDlg*)pParam)->UpdateData(FALSE);
然后调试运行,一切工作正常。
相关文章推荐
- 关于多线程中传递MFC窗口类指针时ASSERT_VALID出错的另类解决 .
- 关于多线程中传递MFC窗口类指针时ASSERT_VALID出错的另类解决
- CWnd::AssertValid()函数执行出错---MFC多线程
- 关于跨线程传递MFC对象指针的探究
- 巧妙解决问题:&CMFCcodeDlg::RunCommands”创建指向成员的指针。MFC多线程调用要求调用的接口必须是全局函数或静态成员函数
- (他山之石)MFC学习之路(三)关于编译【windows核心编程】01-ShowError 源代码出错 ,解决方法!
- 关于实际项目中C++(MFC)指针问题的解决过程
- 关于MFC CFileDlg使用,析构时访问空指针崩溃问题的解决办法
- MFC多线程中创建对话框(create)出错(异常)问题的分析及解决办法
- 一个关于指针的问题,问题很简单,但容易出错,希望大家提出好的解决方法~~~
- 关于MFC对话框不显示或出错的问题解决总结(更新中。。。)
- MFC中ASSERT_VALID fails with NULL pointer的个人解决办法
- 解决MFC连接SqlServer2008出错“无效指针”
- 关于MFC下多线程,在线程中创建非模态对话框以及消息传递
- 关于mfc下多线程socket出错
- [错误记录]关于指针传递获得数据使用错误问题....
- 关于Windows Installer服务出错解决方法收藏。
- 急需解决------关于在两个窗体之间传递参数的问题---------解决了
- 关于 tomcat 启动出错,帮忙解决
- 关于二维数组与二维指针传递参数