PostThreadMessage和SendMessage用法+结合CreateThread多线程讲解

来源:互联网 发布:gre网络课程 编辑:程序博客网 时间:2024/06/05 11:45

提示:有关函数及其参数介绍大家直接百科就行了,这里只介绍具体用法。

一、SendMessage

首先我们来学习一下如何使用SendMessage函数,这个函数在线程中调用后,消息发出到消息接收函数,

该线程必须等到消息接收函数执行完毕才能继续向下执行。这也是它和PostThreadMessage最大的区别。

后者只需要抛出消息,然后继续执行,不需等待接受消息函数执行完。

 

比较完整的做法,六步就可执行完毕,希望读者有些耐心,并且能真正理解其用法的含义。

 

1.

//首先要自定义一个用户消息,我们一般用WM_USER +n来定义消息ID,n要大于100,小于100的已经被系统消息ID占用。

该操作一般位于头文件中。

#define WM_USERLOGIN_RSP WM_USER+102 //账号登录响应

 

2.

//声明一个函数用于接收消息。一般也放在头文件中

afx_msg LRESULT OnUserLogin(WPARAM wParam,LPARAM lParam);

 

3.

//给消息绑定接收函数

ON_MESSAGE(WM_USERLOGIN_RSP,OnUserLogin)

如果是基于MFC编程,在

//将消息和函数绑定

BEGIN_MESSAGE_MAP(CTraVariety, CDialog)

//{{AFX_MSG_MAP(CTraVariety)

、、、、、、、、

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

里面添加这句代码即可

 

4.

//定义消息接收函数,该函数位于下面的第5步中 句柄所代表的区域

LRESULT CTraVariety::OnUserLogin(WPARAM wParam,LPARAM lParam)//登录成功消息

{

CString *nameMsg = (CString *)wParam;

/*********/

}

 

5.该句柄要包含上述第4步中的消息接收函数

//确定一个用来接收消息的句柄,

比如我们可以这样做:

HWND m_hMainWnd;//句柄变量

//给句柄赋值

void CTraVariety::CTPInitWnd(CTraderSpi* UserSpi)

{

// pUserSpi的消息响应窗口设置为本窗口  //传递主窗口句柄:

UserSpi->SetHwnd(this->m_hWnd);

}

SetHwnd()函数定义如下:

void CTraderSpi::SetHwnd(HWND hWnd)

{

m_hMainWnd = hWnd;

}

 

6.最后,你就可以随意使用SendMessage了,第一个参数是你想让这个消息发送到哪个句柄,第二个参数是消息的名,

第三个参数是发送的数据

//发送自定义消息

::SendMessage(m_hMainWnd,WM_USERLOGIN_RSP,(WPARAM)nameMsg,NULL);

 

 

二、PostThreadMessage用法

 

学会了SendMessage的用法,PostThreadMessage其实是一样的,不过SendMessage函数的第一个参数是句柄,

struct HWND__ *类型,但是PostThreadMessage的第一个参数是DWORD类型,用来表示线程ID

所以其使用一般是结合多线程来使用,所以我们有必要谈一下CreateThread()这个函数。

 

CreateThread()属于Windows Api,其实并不建议大家使用,更经常使用的是_beginThread函数,

这个函数属于CRTc running time)函数,是编译器带的,但是底层同样调用了CreateThread

这个我们先不讨论,有关_beginThread使用方法大家可以参考我的另一篇文章——使用_beginThread创建自己的Thread基类。

(不发链接了(*^__^*) 每次发链接都被审核,童鞋们有兴趣就自己翻一翻)。

 

比如现在我们要创建一个日志线程,专门用来存储日志,TradeProc()作为消息接收入口函数,

接收其他各个线程发送来的数据,并不影响其他线程继续工作。

 

1.

//首先要声明变量:

HANDLE  m_hTradeThread; //用来表示线程

DWORD m_dwTradeId; //用来记录线程ID

 

2.

//使用CreateThread将线程和ID绑定到函数TradeProc上,函数名就是入口地址(不多解释)

m_hTradeThread = CreateThread( NULL,0,TradeProc,(LPVOID)this,0,&m_dwTradeId); //日志线程

if (m_hTradeThread == NULL)

{

AfxMessageBox("创建日志记录线程失败!");

  }

 

3.入口函数的定义

//当然函数要提前声明或者位置要在绑定的前方

DWORD WINAPI TradeProc(LPVOID lpParameter) //日志线程函数

{

MSG msg;

while(GetMessage(&msg,NULL,0,0))

{

//做你想做的事情

//such as  :   Public.CreateRecord(LogRecord);

}

return 1;

}

其中的GetMessage()专门用来接收PostThreadMessage()发出的消息,当没有消息发出时,该线程一直处于阻塞状态,

一旦接收到消息,就可以根据消息类型或内容做你想做的事儿。我一般的做法是:创建一个主接收消息线程,

给不同的消息(数据)标识不同的类型,接收到消息后根据消息类型立即抛出到相对应的子线程中,

不影响下一次的消息接收,并可以效率比较高,但是可能会耗费内存喔。当然这些设计思想要根据实际的需求,最后还得取决于你。

 

4.

最后,你又可以随意使用PostThreadMessage()了:

PostThreadMessage(m_dwTradeId,0,(WPARAM)m_tuse,1); //发送消息

 

想详细讨论的童鞋可以加Q 1466231850

0 0
原创粉丝点击