返回信息流最近在做聊天室软件,需要使用MFC的多线程编程,于是就研究总结了一下。小弟技术实力比较菜,有错误的地方欢迎赐教。
一个操作系统的进程、线程通信可以有多种方法,Linux比较常用管道通信,而windows则常用消息传递机制。消息传递这个词说起来比较抽象,但我觉得要实现它并不简单,我花了一天半时间去了解它的技术细节。由于我用到的是MFC框架而不是直接API编程(API编GUI还是需要一定实力的,我显然还不行),所以就总结下MFC的多线程消息传递机制。
1、消息生成:我们使用MFC写界面的时候,里面的按钮控件,我们点击一下就可以执行其中的代码,这就是靠的消息机制。当我们点击按钮后,操作系统自动生成一个消息。
2、消息映射函数。生成消息后,这个消息会传递给消息映射函数。对于按钮控件,这个函数通常可以由MFC自动生成,它的语法如下:
BEGIN_MESSAGE_MAP(MainDialog, CDialog)
ON_BN_CLICKED(IDCANCEL, &MainDialog::OnBnClickedCancel)
//…………
END_MESSAGE_MAP()
这段代码位于当前窗口类的CPP文件中。在BEGIN_MESSAGE_MAP(MainDialog, CDialog)和END_MESSAGE_MAP()之间添加消息映射函数,MainDialog是当前窗口的类,CDialog显然是它的父类。在这个例子里面ON_BN_CLICKED就是消息映射函数,IDCANCEL是点击按钮生成的消息,根据字面意思我们可以看出是个“取消”按钮的消息。这些消息在windows里都有宏定义的。
3、消息响应函数。你点击按钮后,需要程序执行的东西,就是消息响应函数,在上面那个例子中,MainDialog::OnBnClickedCancel则是MainDialog类(即当前窗口)的OnBnClickedCancel方法,这个方法就是IDCANCEL的消息响应函数。当你点击按钮后,需要执行什么,就在这个方法里写什么。
所以我们可以看出,消息映射函数是沟通消息和消息响应函数的纽带。消息传递机制的顺序是:点击按钮——生成消息——消息映射——消息响应。
上面说的是人机交互时的消息传递机制,那么后台线程之间的通信,没有什么点按钮之类的,消息又是如何生成的呢?这里就涉及到用户自定义消息,比如你可以自己宏定义一个消息:
#define UM_MSG WM_USER+111
这里的UM_MSG是你自己命名的,而WM_USER是windows定义的,是一个整数,也就是说从这个整数开始往上你可以自定义消息了,而往下的话就不行,可能已经被windows自己的宏定义采用了(这个我没具体研究过)。为了所谓的保险起见,我这里加个111,感觉比较大了,不会产生冲突了。
定义好之后,再来看看如何产生消息。前面那个例子是点按钮就自动产生,而线程的消息则需要你自己写进线程函数中。可以使用这个函数:
PostMessage((HWND)pParam,UM_MSG,0,0);
第一个参数是要传递的消息对象,是一个窗口的句柄,第二个参数就是我们自己定义的消息,其他两个参数是传给消息响应函数的的,这里我设的是0。线程函数一旦执行到这一句话,那么就产生了UM_MSG这个消息。然后你再在上面说的消息映射区域内添加一个映射函数:
ON_MESSAGE(UM_MSG,&MainDialog::ReceiveMassage)
这里的ON_MESSAGE是windows定义好的用来处理用户自定义消息的映射函数,和上面那个点按钮的不一样。而里面两个参数原理就是和点按钮一样了。也就是说,当某个线程执行到PostMessage语句后,就可以执行MainDialog::ReceiveMassage这个函数了。
顺便说下windows中的多线程,其线程函数并不提倡写在某个类里面作为成员方法,而要作为一个全局函数来存在,如果线程函数要调用类的成员,那个成员必须是static类型。如果硬要把线程函数作为某个类的成员方法,那在声明该方法的时候也必须加static修饰。
说实话,我觉得 Linux编程比windows简单。
这是一条镜像帖。来源:北邮人论坛 / windows / #115084同步于 2011/1/20
Windows机器人发帖
【原创】Windows消息传递机制
wan751
2011/1/20镜像同步0 回复
订阅后,新回复会通过你的通知中心匿名送达。
0 条回复
暂无回复 · 你可以订阅本帖等待新回复。