热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

略谈如何从工作线程中弹出对话框

工作线程,在一些技术文章被称为辅助线程,是相对于主线程而言的。在工作线程中使用界面需要一些技巧。我就曾在工程线程中弹出对话框中遇到过莫名奇妙的错误。下面就我的经验谈谈如何从工作线程中弹出对话框(暂时只

工作线程,在一些技术文章被称为辅助线程,是相对于主线程而言的。在工作线程中使用界面需要一些技巧。我就曾在工程线程中弹出对话框中遇到过莫名奇妙的错误。下面就我的经验谈谈如何从工作线程中弹出对话框(暂时只讲方法,原理还没彻底弄清楚)。

 

实际上在工作线程中直接弹出模式对话框中在debug模式下有时出错(这里的有时的意思是必然会出错,但是不是每次都出错),弹出模式对话框的代码如下:

 

  1. DWORD WINAPI RecvThread(LPVOID lpParam)    // 工作线程函数
  2. {
  3.      CAIDlgProductName dlg;
  4.      if(dlg.DoModal() == IDOK)
  5. {
  6.      ……
  7. }
  8. }

 

 

      

错误截图:

 

 

 

 

如果跟踪DoModal函数,我们进入MFC源码找到出错的地方:

 

 

  1. #ifdef _DEBUG
  2. void CWnd::AssertValid() const
  3. {
  4.     if (m_hWnd == NULL)
  5.         return;     // null (unattached) windows are valid
  6.     // check for special wnd??? values
  7.     ASSERT(HWND_TOP == NULL);       // same as desktop
  8.     if (m_hWnd == HWND_BOTTOM)
  9.         ASSERT(this == &CWnd::wndBottom);
  10.     else if (m_hWnd == HWND_TOPMOST)
  11.         ASSERT(this == &CWnd::wndTopMost);
  12.     else if (m_hWnd == HWND_NOTOPMOST)
  13.         ASSERT(this == &CWnd::wndNoTopMost);
  14.     else
  15.     {
  16.         // should be a normal window
  17.         ASSERT(::IsWindow(m_hWnd));
  18.         // should also be in the permanent or temporary handle map
  19.         CHandleMap* pMap = afxMapHWND();
  20.         ASSERT(pMap != NULL);
  21.         CObject* p;
  22.         // 在下面一句出错
  23.         ASSERT((p = pMap->LookupPermanent(m_hWnd)) != NULL ||
  24.             (p = pMap->LookupTemporary(m_hWnd)) != NULL);
  25.         ASSERT((CWnd*)p == this);   // must be us
  26.         // Note: if either of the above asserts fire and you are
  27.         // writing a multithreaded application, it is likely that
  28.         // you have passed a C++ object from one thread to another
  29.         // and have used that object in a way that was not intended.
  30.         // (only simple inline wrapper functions should be used)
  31.         //
  32.         // In general, CWnd objects should be passed by HWND from
  33.         // one thread to another.  The receiving thread can wrap
  34.         // the HWND with a CWnd object by using CWnd::FromHandle.
  35.         //
  36.         // It is dangerous to pass C++ objects from one thread to
  37.         // another, unless the objects are designed to be used in
  38.         // such a manner.
  39.     }
  40. }

     

实际上当时给我启发的是上面那段Note。我用我浅薄的英文功底翻译一下大意就是:就是上面的asserts发生了同时你正在写的是一个多线程程序,那么asserts发生的原因很可能是你将一个C++对象从一个线程传递给另一个线程同时你无意中使用了那个C++对象(only simple inline wrapper functions should be used(抱歉,这一句不会翻译)),实际上线程之间传递CWnd对象应该传递句柄(HWND)。接收线程应该通过CWnd::FromHandle函数通过传递过来的句柄获取CWnd对象(这里准确的来说应该是CWnd对象的指针)。

 

线程之间传递C++对象是危险的,除非那个对象被设计为以那种方式使用。

 

由上面我想到一种在工作线程中弹出的对话框的办法:

1.       转递视图类句柄给线程函数:

 

  1. HWND HView;
  2. …… // 获取视图类句柄

  3. CreateThread(NULL,0,RecvThread, HView
  4.                 ,0,&dwThreadId);

 

 

   

2.       在线程函数中通过句柄获取视图类指针,获取数据给视图类发送自定义消息:

 

    

  1. DWORD WINAPI RecvThread(LPVOID lpParam)
  2. {
  3.    HWND HView = (HWND)lpParam;
  4.   CWnd* pMyView = CWnd::FromHandle(HView);
  5.   ……
  6.   pMyView ->SendMessage(WM_TASKDLG_MESSAGE,(WPARAM)(&str));
  7.    …….
  8. }

 

 

    

3.   在视图类自定义一个消息函数OnTaskDlgMessage专门处理WM_TASKDLG_MESSAGE消息用于创建对话框:

 

  1. LRESULT CInteAView::OnTaskDlgMessage(WPARAM wParam, LPARAM lParam)
  2. {
  3.      CAIDlgProductName dlg;
  4.      if(dlg.DoModal() == IDOK)
  5.      {
  6.             ……
  7.      }
  8.      return 0;
  9. }

 

 

     

当然上面将视图类换为框架类也是可以的。上面就我的经验谈了一种从工作线程中弹出对话框的办法,不当之处还请大家指点。


推荐阅读
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文详细介绍了 GWT 中 PopupPanel 类的 onKeyDownPreview 方法,提供了多个代码示例及应用场景,帮助开发者更好地理解和使用该方法。 ... [详细]
  • 本文详细介绍了如何使用 Yii2 的 GridView 组件在列表页面实现数据的直接编辑功能。通过具体的代码示例和步骤,帮助开发者快速掌握这一实用技巧。 ... [详细]
  • Android 渐变圆环加载控件实现
    本文介绍了如何在 Android 中创建一个自定义的渐变圆环加载控件,该控件已在多个知名应用中使用。我们将详细探讨其工作原理和实现方法。 ... [详细]
  • 本文介绍如何通过注册表编辑器自定义和优化Windows文件右键菜单,包括删除不需要的菜单项、添加绿色版或非安装版软件以及将特定应用程序(如Sublime Text)添加到右键菜单中。 ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • 作为一名新手,您可能会在初次尝试使用Eclipse进行Struts开发时遇到一些挑战。本文将为您提供详细的指导和解决方案,帮助您克服常见的配置和操作难题。 ... [详细]
  • 在使用 DataGridView 时,如果在当前单元格中输入内容但光标未移开,点击保存按钮后,输入的内容可能无法保存。只有当光标离开单元格后,才能成功保存数据。本文将探讨如何通过调用 DataGridView 的内置方法解决此问题。 ... [详细]
  • 本章将深入探讨移动 UI 设计的核心原则,帮助开发者构建简洁、高效且用户友好的界面。通过学习设计规则和用户体验优化技巧,您将能够创建出既美观又实用的移动应用。 ... [详细]
  • 高效提取PDF页面的实用技巧
    在学习和工作中,我们经常需要与他人共享PDF格式的资料。然而,有时只需要分享部分内容,而不仅仅是整个文档。本文将介绍如何使用福昕阅读器领鲜版高效地提取PDF页面,以提高文件传输效率和查阅便捷性。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • 本文介绍如何通过创建替代插入触发器,使对视图的插入操作能够正确更新相关的基本表。涉及的表包括:飞机(Aircraft)、员工(Employee)和认证(Certification)。 ... [详细]
  • MacOS上高效的SVN管理工具Cornerstone安装指南
    本文详细介绍如何在MacOS上安装和配置高效SVN管理工具Cornerstone,涵盖其主要功能和优化后的性能提升。 ... [详细]
author-avatar
你是我的小心肝啊哈哈
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有