windows窗体线程异常_指针在声明和使用时有何不同

windows窗体线程异常_指针在声明和使用时有何不同在多线程设计中,许多人为了省事,会将对话框类或其它类的指针传给工作线程,而在工作线程中调用该类的成员函数或成员变量等等。但是在Debug版本时,在某些情况下,特别是在工作线程中调用pWnd->UpdateData(FALSE)时,会出现错误。这个错误的原因网上有许多地方讲

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
 在多线程设计中,许多人为了省事,会将对话框类或其它类的指针传给工作线程,而在工作线程中调用该类的成员函数或成员变量等等。

但是在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

/*        CHandleMap* pMap = afxMapHWND();

        ASSERT(pMap != NULL);

        CObject* p;

        ASSERT((p = pMap->LookupPermanent(m_hWnd)) != NULL ||

            (p = pMap->LookupTemporary(m_hWnd)) != NULL);

        ASSERT((CWnd*)p == this);   // must be us

*/

        // 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);

然后调试运行,一切工作正常。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/196839.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 计算机三级数据库技术复习资料总结

    计算机三级数据库技术复习资料总结第7章数据库及数据库对象一、创建及维护数据库1、两大类:系统数据库(自动创建和维护的):master:最重要的数据库,记录所有系统级信息,主要的信息都是存放在这。msdb:保存报警、作业、操作员等信息。(考的不多)model:所有创建数据库的模板。tempdb:临时数据库,每次启动SQL都会重新创建,因此不需要备份。Resource:只读数据库。(没见过考)用户数据库(用户创建和维护)经常考选择题:系统数据库如何备份?(未完成)2、数据库文件分类数据文件:主要数据文件:每个数据

    2022年6月18日
    27
  • rpm 安装 忽略依赖_rpm卸载软件忽略循环依赖

    rpm 安装 忽略依赖_rpm卸载软件忽略循环依赖今天由于某些原因需要卸载掉服务器上的php软件,然后我使用下面命令显示出本机安装的所有和php相关的软件,如下:iteblog$rpm-qa|grepphpphp-mysqlnd-5.6.25-0.1.RC1.el6.remi.x86_64php-fpm-5.6.25-0.1.RC1.el6.remi.x86_64php-pecl-jsonc-1.3.10-1.el6.remi.5.6…

    2022年9月22日
    3
  • 《开源安全运维平台-OSSIM最佳实践》已经上市

    《开源安全运维平台-OSSIM最佳实践》已经上市经多年潜心研究开源技术,历时三年创作的《开源安全运维平台OSSIM最佳实践》一书即将出版。该书用100多万字记录了作者10多年的OSSIM研究应用成果,重点展示了开源安全管理平台OSSIM在大型企业网运维管理中的实践。国内目前也有各式各样的运维系统,经过笔者对比分析得出这些工具无论在功能上、性能上还是在安全和稳定性易用性上都无法跟OSSIM系统想媲美,而且很多国内的开源安全运维项目在发布几年后就逐步淡出了舞台,而OSSIM持续发展了十多年。

    2025年7月26日
    5
  • Shell内值命令之exit「建议收藏」

    Shell内值命令之exit「建议收藏」Shell内值命令之exit介绍: exit用于退出当前shell环境进程结束运行,并且可以返回一个状态码.一般使用$?可以获取状态码.语法: 正确退出语法exit#默认返回状态码0,一般代表命令执行成功 错误退出语法exit非0数字#数字建议的范围0-255一般代表命令执行失败exit应用场景 1.结束当前shell进程 2.当shell进程执行出错退出时,可以返回不同的状态值代表不同的错误. 比如执行一个脚本文件里面操作一个文件时,可以返回1表示文件不存在,2表示

    2022年10月9日
    1
  • Adobe Photoshop CC 打开时报错~配置错误:请卸载并重新安装该产品

    Adobe Photoshop CC 打开时报错~配置错误:请卸载并重新安装该产品

    2021年9月13日
    123
  • 谷歌创始人是谁_谷歌创始人的故事

    谷歌创始人是谁_谷歌创始人的故事·布林更多的关注。最新一期的《莫斯科新闻》称,如果举世瞩目的诺贝尔奖设有IT奖的话,这位脸上总是挂着招牌式微笑的年轻人注定是该奖项最有竞争力的人选。他创建的Google成为人们使用互联网的一种重要方式,使每个人与很多问题的答案之间只有点击一下鼠标那么远,Google正像当年的甲壳虫乐队那样风靡全球。  谢尔盖·布林出生在前苏联一个犹太人家庭。5岁那年,布林跟随父母一起移民美国,从而开始了他美

    2022年9月1日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号