C++多线程编程(三)线程间通信

简介: 多线程编程之三——线程间通讯作者:韩耀旭原文地址:http://www.vckbase.com/document/viewdoc/?id=1707 七、线程间通讯  一般而言,应用程序中的一个次要线程总是为主线程执行特定的任务,这样,主线程和次要线程间必定有一个信息传递的渠道,也就是主线程和次要线程间要进行通信。

多线程编程之三——线程间通讯

作者:韩耀旭

原文地址:http://www.vckbase.com/document/viewdoc/?id=1707

 

七、线程间通讯

  一般而言,应用程序中的一个次要线程总是为主线程执行特定的任务,这样,主线程和次要线程间必定有一个信息传递的渠道,也就是主线程和次要线程间要进行通信。这种线程间的通信不但是难以避免的,而且在多线程编程中也是复杂和频繁的,下面将进行说明。

  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; 
    代表加数的大小。

    分别双击三个单选按钮,添加消息响应函数:
     
      
    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] view plain copy
    1. BOOL CMultiThread7Dlg::OnInitDialog()  
    2. {  
    3. ……  
    4.     ((CButton*)GetDlgItem(IDC_RADIO1))->SetCheck(TRUE);  
    5.     nAddend=10;  
    6. ……  
    在MultiThread7Dlg.h中添加:
     
      
    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,添加消息响应函数:
     
      
    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 中添加
     
      
    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:http://blog.csdn.net/yanpingsz/article/details/5891693 

目录
相关文章
|
2月前
|
监控 Linux C++
4步实现C++插件化编程,轻松实现功能定制与扩展(2)
本文是《4步实现C++插件化编程》的延伸,重点介绍了新增的插件“热拔插”功能。通过`inotify`接口监控指定路径下的文件变动,结合`epoll`实现非阻塞监听,动态加载或卸载插件。核心设计包括`SprDirWatch`工具类封装`inotify`,以及`PluginManager`管理插件生命周期。验证部分展示了插件加载与卸载的日志及模块状态,确保功能稳定可靠。优化过程中解决了动态链接库句柄泄露问题,强调了采纳用户建议的重要性。
72 17
4步实现C++插件化编程,轻松实现功能定制与扩展(2)
|
3月前
|
存储 缓存 C++
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
|
3月前
|
Python
python3多线程中使用线程睡眠
本文详细介绍了Python3多线程编程中使用线程睡眠的基本方法和应用场景。通过 `time.sleep()`函数,可以使线程暂停执行一段指定的时间,从而控制线程的执行节奏。通过实际示例演示了如何在多线程中使用线程睡眠来实现计数器和下载器功能。希望本文能帮助您更好地理解和应用Python多线程编程,提高程序的并发能力和执行效率。
86 20
|
3月前
|
存储 机器学习/深度学习 编译器
【C++终极篇】C++11:编程新纪元的神秘力量揭秘
【C++终极篇】C++11:编程新纪元的神秘力量揭秘
|
3月前
|
安全 Java C#
Unity多线程使用(线程池)
在C#中使用线程池需引用`System.Threading`。创建单个线程时,务必在Unity程序停止前关闭线程(如使用`Thread.Abort()`),否则可能导致崩溃。示例代码展示了如何创建和管理线程,确保在线程中执行任务并在主线程中处理结果。完整代码包括线程池队列、主线程检查及线程安全的操作队列管理,确保多线程操作的稳定性和安全性。
|
3月前
|
存储 算法 C++
深入浅出 C++ STL:解锁高效编程的秘密武器
C++ 标准模板库(STL)是现代 C++ 的核心部分之一,为开发者提供了丰富的预定义数据结构和算法,极大地提升了编程效率和代码的可读性。理解和掌握 STL 对于 C++ 开发者来说至关重要。以下是对 STL 的详细介绍,涵盖其基础知识、发展历史、核心组件、重要性和学习方法。
|
3月前
|
存储 安全 算法
深入理解C++模板编程:从基础到进阶
在C++编程中,模板是实现泛型编程的关键工具。模板使得代码能够适用于不同的数据类型,极大地提升了代码复用性、灵活性和可维护性。本文将深入探讨模板编程的基础知识,包括函数模板和类模板的定义、使用、以及它们的实例化和匹配规则。
|
3月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
69 17
|
3月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
68 26
|
5月前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
385 2
下一篇
oss创建bucket