MFC多线程编的可能

之所以是“可能”,因为这里有个重点就是临时对象是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,因此将不发生任何事。

步骤/方法

  • 01

    因此合理(并不一定最好)的解决方法是向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 ); }

  • 02

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

  • 03

    多线程的程序设计应该注意些什么呢 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语句有过之而无不及。好的多线程程序,应该是尽量少的使用线程。这句话怎么理解呐,就是说尽量统一一块数据共享区存放数据队列,工作子线程从队列中取数据,处理,再放回数据,这样才会模块化,对象化;而不是每个数据都起一个工作子线程处理,处理完了就关闭,写的时候虽然直接,等维护起来就累了。

(0)

相关推荐

  • MFC多线程编程实例

    一般情况下,调用AfxBeginThread()来一次性地创建并启动一个线程,但是也可以通过两步法来创建线程:首先创建CWinThread类的一个 对象,然后调用该对象的成员函数CreateThrea ...

  • MFC对多线程编程的支持

    摘要:关于MFC对多线程编程的支持深入研究. 步骤/方法 01 例程3 MultiThread3 传送一个结构体给一个线程函数也是可能的,可以通过传送一个指向结构体的指针参数来完成.先定义一个结构体: ...

  • WinXP系统里让IE支持多线程下载的设置方法

    随着电脑的普及化和网络速度的提高很多人会进行网上冲浪在网上下载电影来观看,有时我们会同时下载多个文件,为了支持多线程下载通常都会选择专业软件进行下载,因为不少人认为ie浏览器是不支持多线程下载只支持单 ...

  • Linux下如何实现shell多线程编程以提高应用程序的响应

    Linux中多线程编程拥有提高应用程序的响应、使多cpu系统更加有效等优点,下面小编将通过Linux下shell多线程编程的例子给大家讲解下多线程编程的过程,一起来了解下吧。 #!/bin/bash ...

  • 什么是多线程和多进程

    线程和进程都是现在电脑概念里比较时髦的用语,什么是多线程,什么是多进程?本文详细的给您介绍一下,希望能增进您对当代电脑技术的了解,有不到之处,还往高手予以更正.进程(英语:Process,中国大陆译作 ...

  • VS如何为基于对话框的MFC添加菜单及菜单项事件

    新建出来的基于对话框的MFC工程是没有菜单的,如何在对话框中添加菜单?又如何给菜单的菜单项添加事件应用响应?下面小编来具体描述一下,希望能帮助到一些人. 操作方法 01 新建一个基于对话框的MFC工程 ...

  • 易语言多线程软件崩溃之停止工作的解决办法

    易语言初学者写多线程的时候,写出来的程序经常是调试的时候就一切正常,静态编绎以后就出现各种崩溃和假死,很是让人头疼,然后到处求人,甚至怀疑是易语言BUG,不过我可以告诉大家, 易语言多线程本身是稳定的 ...

  • 按键精灵实现多线程多开脚本教程

    "多线程到底怎么实现?好复杂!" 小编时常在论坛里,看到有童鞋发出这样的疑问.小编觉得多线程就好似冰山美人,外冷内热.乍一看,好像很不好相处,近一步,则会发现其实她很温柔. 到底有 ...

  • 如何在Visual Studio 2015中创建MFC窗体应用

    我们在使用Visual Studio 2015创建桌面应用的时候,最经常遇到的就是Winform和MFC了,那么如何在Visual Studio 2015中创建MFC窗体应用呢?下面小编给大家分享一下 ...