1、 之所以是“可能”,因为这里有个重点就是临时对象是HWND操作的封装,不是窗口类的封装。因此所有的HWND临时对象都是CWnd的实例,即使上面强行转换为CAbcDialog*也依旧是CWnd*,所以在ASSERT_VALID里调用CAbcDialog::AssertValid时,其定义了一些附加检查,则可能发现这是一个CWnd的实例而非一个CAbcDialog实例,导致断言失败。因此应将CAbcDialog全部换成CWnd,这下虽然不断言失败了,但依旧错误(先不提pDialog->m_Data怎么办),因为临时对象是HWND操作的封装,而不幸的是UpdateData只是MFC自己提供的一个对话框数据交换的机制(DDX)的操作,其不是通过向HWND发送消息来实现的,而是通过虚函数机制。因此在UpdateData中调用实例的DoDataExchange将不能调用CAbcDialog::DoDataExchange,而是调用CWnd::DoDataExchange,因此将不发生任何事。

因此合理(并不一定最好)的解决方法是向CAbcDialog的实例发送一个消息,而通过一个中间变量(如一全局变量)来传递数据,而不是使用CAbcDialog::m_Data。当然,如果数据少,比如本例,就应该将数据作为消息参数进行传递,减少代码的复杂性;数据多则应该通过全局变量传递,减少了缓冲的管理费用。修改后如下:
  #define AM_DATANOTIFY ( WM_USER + 1 )
  static DWORD g_Data = 0;
  DWORD WINAPI ThreadProc( void *pData ) // 线程函数(比如用于从COM口获取数据)
  {
  // 数据获取循环
  // 数据获得后放在变量i中
  g_Data = i;
  CWnd *pWnd = CWnd::FromHandle( reinterpret_cast< HWND >( pData ) );
  ASSERT_VALID( pWnd ); // 本例应该直接调用平台SendMessage而不调用包装类的,这里只是演示
  pWnd->SendMessage( AM_DATANOTIFY, 0, 0 );
  …
  }
  BEGIN_MESSAGE_MAP( CAbcDialog, CDialog )
  …
  ON_MESSAGE( AM_DATANOTIFY, OnDataNotify )
  …
  END_MESSAGE_MAP()
  BOOL CAbcDialog::OnInitDialog()
  {
  CDialog::OnInitDialog();
  // 其他初始化代码
  CreateThread( NULL, 0, ThreadProc, m_hWnd, 0, NULL ); // 创建线程
  return TRUE;
  }
  LRESULT CAbcDialog::OnDataNotify( WPARAM /* wParam */, LPARAM /* lParam */ )
  {
  UpdateData( FALSE );
  return 0;
  }
  void CAbcDialog::DoDataExchange( CDataExchange *pDX )
  {
  CDialog::DoDataExchange( pDX );
  DDX_Text( pDX, IDC_EDIT1, g_Data );
  }

 
 

2、注意事项
  “线程安全”是一个什么概念?
  以前常听高手告诫MFC对象不要跨线程使用,因为MFC不是线程安全的。比如CWnd对象不要跨线程使用,可以用窗口句柄(HWND)代替。CSocket/CAsyncSocket对象不要跨线程使用,用SOCKET句柄代替.那么到底什么是线程安全呢?什么时候需要考虑?如果程序涉及到多线程的话,就应该考虑线程安全问题。比如说设计的接口,将来需要在多线程环境中使用,或者需要跨线程使用某个对象时,这个就必须考虑了。关于线程安全也没什么权威定义。在这里我只说说我的理解:所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。
  一般而言“线程安全”由多线程对共享资源的访问引起。如果调用某个接口时需要我们自己采取同步措施来保护该接口访问的共享资源,则这样的接口不是线程安全的.MFC和STL都不是线程安全的. 怎样才能设计出线程安全的类或者接口呢?如果接口中访问的数据都属于私有数据,那么这样的接口是线程安全的.或者几个接口对共享数据都是只读操作,那么这样的接口也是线程安全的.如果多个接口之间有共享数据,而且有读有写的话,如果设计者自己采取了同步措施,调用者不需要考虑数据同步问题,则这样的接口是线程安全的,否则不是线程安全的。

3、多线程的程序设计应该注意些什么呢
  1、尽量少的使用全局变量、static变量做共享数据,尽量使用参数传递对象。被参数传递的对象,应该只包括必需的成员变量。所谓必需的成员变量,就是必定会被多线程操作的。很多人图省事,会把this指针(可能是任意一个对象指针)当作线程参数传递,致使线程内部有过多的操作权限,对this中的参数任意妄为。整个程序由一个人完成,可能会非常注意,不会出错,但只要一转手,程序就会面目全非。当两个线程同时操作一个成员变量的时候,程序就开始崩溃了,更糟的是,这种错误很难被重现。(我就在郁闷这个问题,我们是几个人,把程序编成debug版,经过数天使用,才找到错误。而找到错误只是开始,因为你要证明这个bug被修改成功了,也非常困难。)其实,线程间数据交互大多是单向的,在线程回调函数入口处,尽可能的将传入的数据备份到局部变量中(当然,用于线程间通讯的变量不能这么处理),以后只对局部变量做处理,可以很好的解决这种问题。
  2、在MFC中请慎用线程。因为MFC的框架假定你的消息处理都是在主线程中完成的。首先窗口句柄是属于线程的,如果拥有窗口句柄的线程退出了,如果另一个线程处理这个窗口句柄,系统就会出现问题。而MFC为了避免这种情况的发生,使你在子线程中调用消息(窗口)处理函数时,就会不停的出Assert错误,烦都烦死你。典型的例子就时CSocket,因为CSocket是使用了一个隐藏窗口实现了假阻塞,所以不可避免的使用了消息处理函数,如果你在子线程中使用CSocket,你就可能看到assert的弹出了。
  3、不要在不同的线程中同时注册COM组件。两个线程,一个注册1.ocx, 2.ocx, 3.ocx, 4.ocx; 而另一个则注册5.ocx, 6.ocx, 7.ocx, 8.ocx,结果死锁发生了,分别死在FreeLibrary和DllRegisterServer,因为这8个ocx是用MFC中做的,也可能是MFC的Bug,但DllRegisterServer却死在GetModuleFileName里,而GetModuleFileName则是个API唉!如果有过客看到,恰巧又知道其原因,请不吝赐教。
  4、不要把线程搞的那么复杂。很多初学者,恨不能用上线程相关的所有的函数,这里互斥,那里等待,一会儿起线程,一会儿关线程的,比起goto语句有过之而无不及。好的多线程程序,应该是尽量少的使用线程。这句话怎么理解呐,就是说尽量统一一块数据共享区存放数据队列,工作子线程从队列中取数据,处理,再放回数据,这样才会模块化,对象化;而不是每个数据都起一个工作子线程处理,处理完了就关闭,写的时候虽然直接,等维护起来就累了。

MFC多线程编的可能的更多相关文章

  1. iOS多线程编程之NSThread的使用

      目录(?)[-] 简介 iOS有三种多线程编程的技术分别是 三种方式的有缺点介绍 NSThread的使用 NSThread 有两种直接创建方式 参数的意义 PS不显式创建线程的方法 下载图片的例子 ...

  2. iOS多线程编程之NSThread的使用(转)

    本文由http://blog.csdn.net/totogo2010/原创 1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation  ...

  3. MFC 多线程

    MFC对多线程编程的支持 MFC中有两类线程,分别称之为工作者线程和用户界面线程.二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息   队列和消息循环. 工作者线程没有消息机制,通 ...

  4. MFC多线程内存泄漏问题&amp;解决方法

    在用visual studio进行界面编程时(如MFC),前台UI我们能够通过MFC的消息循环机制实现.而对于后台的数据处理.我们可能会用到多线程来处理. 那么对于大多数人(尤其是我这样的菜鸟),一个 ...

  5. [转] iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用

    介绍: Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其他的对称多处理系统的系统.这建立在任务并行执行的线程池模式的基础上的.它首 ...

  6. [转] iOS多线程编程之NSOperation和NSOperationQueue的使用

    <iOS多线程编程之NSThread的使用> 介绍三种多线程编程和NSThread的使用,这篇介绍NSOperation的使用. 使用 NSOperation的方式有两种, 一种是用定义好 ...

  7. [转]iOS多线程编程之NSThread的使用

    1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue ...

  8. iOS 多线程编程之Grand Central Dispatch(GCD)

    介绍: Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其它的对称多处理系统的系统.这建立在任务并行运行的线程池模式的基础上的. 它 ...

  9. MFC多线程各种线程用法 .

    http://blog.csdn.net/qq61394323/article/details/9328301 一.问题的提出 编写一个耗时的单线程程序: 新建一个基于对话框的应用程序SingleTh ...

随机推荐

  1. 一种用css实现图片在父框中等比缩放并垂直居中的办法

    一个网页中往往会有很多图片,而网站的编辑上传图片时可能并不一定按照为父框设定的那个宽高来传,这样图片往往会将父框撑开或者被父框截断.一种比较好的解决的办法是这样的: HTML代码结构: <div ...

  2. memcached学习笔记——存储命令源码分析上篇

    原创文章,转载请标明,谢谢. 上一篇分析过memcached的连接模型,了解memcached是如何高效处理客户端连接,这一篇分析memcached源码中的process_update_command ...

  3. lazy loading img 图片延迟加载

    http://yunpan.cn/cVsjPW6dgbcsh (提取码:b5db)

  4. [每日一题JS] 正则表达式

    判断字符串是否是这样组成的,第一个必须是字母,后面可以是字母.数字.下划线,总长度为5-20 var reg = /\b[a-zA-Z]{1}[a-zA-Z0-9_]{4,19}\b/; var fl ...

  5. Powershell 设置数值格式 1

    设置数值格式 1 6 6月, 2013  在 Powershell tagged 字符串 / 数字 / 文本 / 日期 / 格式化 by Mooser Lee 格式化操作符 -f 可以将数值插入到字符 ...

  6. Powershell过滤管道结果

    通过管道可以过滤某些对象和对象的属性,这个功能很实用,因为很多时候我们并不是对所有的结果感兴趣,可能只会对某些结果感兴趣.如果要过滤对象可以使用Where-Object:如果要过滤对象的属性,可以使用 ...

  7. Handler处理长时间事件

    当我们在处理一些比较长时间的事件时候,比如读取网络或者数据库的数据时候,就要用到Handler,有时候为了不影响用户操作应用的流畅还要开多一个线程来区别UI线程,在新的线程里面处理长时间的操作.开发的 ...

  8. 转:linux shell 数组建立及使用技巧

    linux shell在编程方面比windows 批处理强大太多,无论是在循环.运算.已经数据类型方面都是不能比较的. 下面是个人在使用时候,对它在数组方面一些操作进行的总结. 1.数组定义 [che ...

  9. spin.js无图片实现loading进度条,支持但非依赖jquery

    特点: 1.无图片,无外部CSS 2.无依赖(支持jQuery,但非必须) 3.高度可配置 4.分辨率无关 5.旧版本IE不支持时,采用VML支持 6.使用关键帧动画,采用setTimeout() 7 ...

  10. Linux企业级项目实践之网络爬虫(18)——队列处理

    所有的URL都接受管理,并在此进行流动.URL从管理模块的存储空间开始,一直到最后输出给磁盘上的URL索引,都由此部分调度.首先,给出URL调度的一般过程,如图所示.其流程的各个具体操作,后面详述.要 ...