线程间通信主要有两种方法:
1、使用全局变量进行通信
由于属于同一个进程的各个线程共享操作系统分配给该进程的资源,故而解决线程通信的最简单一个方法就是使用全局变量。对于标准类型的全局变量,建议使用volatile修饰符,它告诉程序无需对该变量作任何优化,即无需将它放到一个寄存器中,并且该值可被外部改变。如果线程间所需传递的信息比较复杂,那么可以定义一个结构体,通过传递指向该结构体的指针进行传递信息。
2、使用自定义消息
我们可以在一个线程的执行函数中向另一个线程发送自定义消息来达到通信的目的。利用Windows操作系统的消息驱动机制,当一个线程发出一条消息时,操作系统首先接到该消息,然后把该消息转发给目标线程,接受消息的线程必须已经建立了消息循环。
下面是一个简单的例子,演示如何使用自定义消息进行线程间通信。首先,主线程向CCalculateThread线程发送消息WM_CALCULATE,CCalculateThread线程收到消息后进行计算,再向主线程发送消息WM_DISPLAY,主线程接收到该消息后将结果显示。
主要步骤:
1、建立一个对话框工程ThreadCommunication,在其中添加三个单选按钮IDC_RADIO1,IDC_RADIO2,IDC_RADIO3,标题分别为1+2+3+...+10,1+2+3+...+50,1+2+3+...+100,加入按钮IDC_SUM,标题为“求和”,加入一个标签框IDC_STATIC用于显示结果。
2、在该对话框类中定义protected型变量 int Addent,在OnInitDialog()中完成单选按钮和Addent的初始化,即((CButton*)GetDlgItem(IDC_RADIO1))->SetCheck(TRUE);和Addent=10。
3、添加三个按钮消息响应函数,即双击每个按钮,在三个响应函数里面分别加入Addent=10; Addent=50; Addent=100;
4、利用类向导新建一个基于CWinThread的线程类CCalThread,在头文件中定义一个消息#define WM_DISPLAY WM_USER+1 ,然后在类里面定义一个消息处理函数如下
protected:
afx_msg void OnCalculate(UNIT wParam , LONG lParam);
5、在消息映射表中,为接收到的消息添加消息处理函数,由于在CWinThread类里面,所以用ON_THREAD_MESSAGE替代ON_MESSAGE,如下:
ON_THREAD_MESSAGE(WM_CALCULATE,&CCalculate::OnCalculate)
这里的这个消息是接收的消息,要在对话框类头文件里面定义(见下面步骤),为了使用这个消息,需要包含对话框头文件,即#include " ThreadCommunication.h "
6、实现这个消息响应函数,如下:
void CCalculate::OnCalculate(UNIT wParam , LONG lParam)
{
int temp=(int)wParam;
int sum=0;
for(int i=1;i<=temp;i++)
{
sum=sum+i;
}
Sleep(100);
::Postmessage(((HWND)GetMainWnd()->GetSafeHwnd()) , WM_DISPLAY,sum,NULL);
}
到此为止,线程类里面的工作已经搞定,接下来主要在对话框里面做工作了。
7、同理,在对话框类里面需要定义一个消息用于发送,增加一个消息映射为了处理接收到的消息,定义和实现该消息处理函数。代码如下:
头文件里:
#include " CalThread.h "
#define WM_CALCULATE WM_USER+2
protected :
afx_msg LRESULT OnDisPlay(UNIT wParam , LONG lParam);
消息映射表里面添加
ON_MESSAGE(WM_DISPLAY,&CThreadCommunicationDlg::OnDisplay)
Cpp里面实现消息处理函数
LRESULT CThreadCommunicationDlg::OnDisPlay(UNIT wParam , LONG iParam)
{
int result=(int)wParam;
::SetDlgItemInt(GetsafeHwnd(),IDC_STATIC,result,TRUE);
return 0;
}
8、最后就是在对话框里面开启这个线程了,双击求和按钮,自动添加消息响应函数,在该函数里面添加如下代码:
CWinThread* CalThread->AfxBeginThread(RUNTIME_CLASS(CCALThread));
Sleep(100);
CalThread->PostThreadMessage(WM_CALCULATE,Addent,NULL);