C++多线程编程(三)线程间通信
多线程编程之三——线程间通讯
作者:
原⽂地址:
七、线程间通讯
  ⼀般⽽⾔,应⽤程序中的⼀个次要线程总是为主线程执⾏特定的任务,这样,主线程和次要线程间必定有⼀个信息传递的渠道,也就是主线程和次要线程间要进⾏通信。这种线程间的通信不但是难以避免的,⽽且在多线程编程中也是复杂和频繁的,下⾯将进⾏说明。
1. 使⽤全局变量进⾏通信
由于属于同⼀个进程的各个线程共享操作系统分配该进程的资源,故解决线程间通信最简单的⼀种⽅法是使⽤全局变量。对于标准类型的全局变量,我们建议使⽤volatile 修饰符,它告诉编译器⽆需对该变量作任何的优化,即⽆需将它放到⼀个寄存器中,并且该值可被外部改变。如果线程间所需传递的信息较复杂,我们可以定义⼀个结构,通过传递指向该结构的指针进⾏传递信息。
2. 使⽤⾃定义消息
我们可以在⼀个线程的执⾏函数中向另⼀个线程发送⾃定义的消息来达到通信的⽬的。⼀个线程向另外⼀个线程发送消息是通过操作系统实现的。利⽤Windows操作系统的消息驱动机制,当⼀个线程发出⼀条消息时,操作系统⾸先接收到该消息,然后把该消息转发给⽬标线程,接收消息的线程必须已经建⽴了消息循环。
例程7 MultiThread7
  该例程演⽰了如何使⽤⾃定义消息进⾏线程间通信。⾸先,主线程向CCalculateThread线程发送消息
WM_CALCULATE,CCalculateThread线程收到消息后进⾏计算,再向主线程发送WM_DISPLAY消息,主线程收到该消息后显⽰计算结果。
1. 建⽴⼀个基于对话框的⼯程MultiThread7,在对话框IDD_MULTITHREAD7_DIALOG中加⼊三个单选按钮
IDC_RADIO1,IDC_RADIO2,IDC_RADIO3,标题分别为1+2+3+4+......+10,1+2+3+4+......+50,1+2+3+4+......+100。加⼊按钮IDC_SUM,标题为“求和”。加⼊标签框IDC_STATUS,属性选中“边框”;
2. 在MultiThread7Dlg.h中定义如下变量:
protected:  int nAddend;
代表加数的⼤⼩。
分别双击三个单选按钮,添加消息响应函数:
[cpp]
1. void CMultiThread7Dlg::OnRadio1()
2. {
3.    nAddend=10;
4. }
5.
6. void CMultiThread7Dlg::OnRadio2()
7. {
8.    nAddend=50;
9.
10. }
11.
12. void CMultiThread7Dlg::OnRadio3()
13. {
14.    nAddend=100;
15.
16. }
并在OnInitDialog函数中完成相应的初始化⼯作:
[c-sharp]
1. BOOL CMultiThread7Dlg::OnInitDialog()
2. {
3. ……
4.    ((CButton*)GetDlgItem(IDC_RADIO1))->SetCheck(TRUE);
5.    nAddend=10;
6. ……
在MultiThread7Dlg.h中添加:
[cpp]
1. #include "CalculateThread.h"
2. #define WM_DISPLAY WM_USER+2
3. class CMultiThread7Dlg : public CDialog
4. {
5. // Construction
6. public:
7.    CMultiThread7Dlg(CWnd* pParent = NULL); // standard constructor
8.    CCalculateThread* m_pCalculateThread;
9. ……
10. protected:
11. int nAddend;
12. LRESULT OnDisplay(WPARAM wParam,LPARAM lParam);
13. ……
14.
15. 在MultiThread7Dlg.cpp中添加:
16. BEGIN_MESSAGE_MAP(CMultiThread7Dlg, CDialog)
17. ……
18.    ON_MESSAGE(WM_DISPLAY,OnDisplay)
19. END_MESSAGE_MAP()
20.
21. LRESULT CMultiThread7Dlg::OnDisplay(WPARAM wParam,LPARAM lParam)
22. {
23. int nTemp=(int)wParam;
24.    SetDlgItemInt(IDC_STATUS,nTemp,FALSE);
25.
26.  return 0;
27.
28. }
进程间通信和线程间通信的区别
以上代码使得主线程类CMultiThread7Dlg可以处理WM_DISPLAY消息,即在IDC_STATUS标签框中显⽰计算结果。
3. 双击按钮IDC_SUM,添加消息响应函数:
[cpp]
1. void CMultiThread7Dlg::OnSum()
2. {
3.    m_pCalculateThread=
4.        (CCalculateThread*)AfxBeginThread(RUNTIME_CLASS(CCalculateThread));
5.
6.    Sleep(500);
7.
8.    m_pCalculateThread->PostThreadMessage(WM_CALCULATE,nAddend,NULL);
9. }
OnSum()函数的作⽤是建⽴CalculateThread线程,延时给该线程发送WM_CALCULATE消息。
4. 右击⼯程并选中“New Class…”为⼯程添加基类为 CWinThread 派⽣线程类 CCalculateThread。
在⽂件CalculateThread.h 中添加
[cpp]
1. #define WM_CALCULATE WM_USER+1
2. class CCalculateThread : public CWinThread
3. {
4. ……
5. protected:
6.    afx_msg LONG OnCalculate(UINT wParam,LONG lParam);
7. ……
8.
9. 在⽂件CalculateThread.cpp中添加
10. LONG CCalculateThread::OnCalculate(UINT wParam,LONG lParam)
11. {
12. int nTmpt=0;
13.    for(int i=0;i<=(int)wParam;i++)
14.    {
15.        nTmpt=nTmpt+i;
16.    }
17.
18.    Sleep(500);
19.    ::PostMessage((HWND)(GetMainWnd()->GetSafeHwnd()),WM_DISPLAY,nTmpt,NULL);
20.
21.    return 0;
22. }
23. BEGIN_MESSAGE_MAP(CCalculateThread, CWinThread)
24.    //{{AFX_MSG_MAP(CCalculateThread)
25.        // NOTE - the ClassWizard will add and remove mapping macros here.
26.    //}}AFX_MSG_MAP
27.    ON_THREAD_MESSAGE(WM_CALCULATE,OnCalculate)
28. //和主线程对⽐,注意它们的区别
29. END_MESSAGE_MAP()
在CalculateThread.cpp⽂件的开头添加⼀条:
#include "MultiThread7Dlg.h"
  以上代码为 CCalculateThread 类添加了 WM_CALCULATE 消息,消息的响应函数是 OnCalculate,其功能是根据参数wParam 的值,进⾏累加,累加结果在临时变量nTmpt中,延时0.5秒,向主线程发送WM_DISPLAY消息进⾏显⽰,nTmpt作为参数传递。
编译并运⾏该例程,体会如何在线程间传递消息。
(未完待续)
from:blog.csdn/yanpingsz/article/details/5891693

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。