主线程向子线程发送消息

参考链接:https://www.cnblogs.com/ranjiewen/p/5729539.html

1. 创建线程语句

    HANDLE hThread;
DWORD dwThreadId[3];
for (int i = 0; i < 3; i++) {
hThread = CreateThread(NULL, 0, FunProc, &i, 0, &dwThreadId[i]);
CloseHandle(hThread);
}

2. 向子线程发送消息语句。

  a. 在.cpp最上面定义#define MY_MSG WM_USER+100

        for (int j = 0; j < 3; j++) {
if (!PostThreadMessage(dwThreadId[j], MY_MSG, 0, 0)) {
printf("post message failed,errno:%d\n", ::GetLastError());
}
}

3.1 线程函数接收消息不阻塞

DWORD WINAPI FunProc(LPVOID lpParameter)
{
MSG msg;
int i = 0;
while (TRUE)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (msg.message == MY_MSG)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
i++;
printf("i = %d\n", i);
Sleep(1000);
}
return 0;
}

此时接收消息用的是PeekMessage函数,此函数不会阻塞线程。如果此时有消息传来,那么返回的是TRUE,如果没有消息传来,返回的就是FALSE。这个函数的含义是每隔一秒输出一次i,直到有消息传递给线程,那么线程结束。

3.2 线程接收消息阻塞

DWORD WINAPI FunProc(LPVOID lpParameter)
{
MSG msg;
int i = 0;
BOOL stop_thread = FALSE;
while (!stop_thread)
{
if (GetMessage(&msg, 0, 0, 0)) {
switch (msg.message)
{
case MY_MSG:
stop_thread = TRUE;
break;
}
}
i++;
printf("i = %d\n", i);
Sleep(1000);
}
return 0;
}

此时接收消息用的是GetMessage函数,此函数会阻塞在if语句那儿,直到有消息传来,才会继续下去,所以这个线程只会输出一次i就结束了。

SubWin1.cpp

// SubWin1.cpp : implementation file
// #include "stdafx.h"
#include "Project2.h"
#include "SubWin1.h"
#include "afxdialogex.h"
#include "resource.h" // SubWin1 dialog
#define MY_MSG WM_USER+100
//const int MAX_INFO_SIZE = 20; IMPLEMENT_DYNAMIC(SubWin1, CDialog) SubWin1::SubWin1(CWnd* pParent /*=nullptr*/)
: CDialog(IDD_SubWin1, pParent)
{ } SubWin1::~SubWin1()
{
} void SubWin1::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
} BEGIN_MESSAGE_MAP(SubWin1, CDialog)
ON_WM_TIMER()
ON_WM_CLOSE()
END_MESSAGE_MAP() // SubWin1 message handlers DWORD WINAPI FunProc(LPVOID lpParameter)
{
MSG msg;
//DWORD id_thread = GetCurrentThreadId();
//printf("id_thread = %d\n", id_thread);
int i = 0;
BOOL stop_thread = FALSE;
while (!stop_thread)
{
//if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
//{
// if (msg.message == MY_MSG)
// break;
// TranslateMessage(&msg);
// DispatchMessage(&msg);
//}
if (GetMessage(&msg, 0, 0, 0)) {
switch (msg.message)
{
case MY_MSG:
stop_thread = TRUE;
break;
}
}
i++;
printf("i = %d\n", i);
Sleep(1000);
}
return 0;
} BOOL SubWin1::OnInitDialog()
{
CDialog::OnInitDialog(); // TODO: Add extra initialization here HANDLE hThread;
for (int i = 0; i < 3; i++) {
hThread = CreateThread(NULL, 0, FunProc, &i, 0, &dwThreadId[i]);
CloseHandle(hThread);
} SetTimer(0, 1000, NULL); //设置一秒刷新一次 return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
} void SubWin1::OnTimer(UINT_PTR nIDEvent)
{
// TODO: Add your message handler code here and/or call default
escape_time++;
if (escape_time > 10) {
for (int j = 0; j < 3; j++) {
if (!PostThreadMessage(dwThreadId[j], MY_MSG, 0, 0)) {
printf("post message failed,errno:%d\n", ::GetLastError());
}
}
EndDialog(0x00);
} CDialog::OnTimer(nIDEvent);
} void SubWin1::OnClose()
{
// TODO: Add your message handler code here and/or call default
for (int j = 0; j < 3; j++) {
if (!PostThreadMessage(dwThreadId[j], MY_MSG, 0, 0)) {
printf("post message failed,errno:%d\n", ::GetLastError());
}
} CDialog::OnClose();
}

这个程序起源于创建一个Dll带MFC库,前面有讲过这一章节内容。

C++第五十二篇 -- 多线程之消息传递的更多相关文章

  1. 第五十二篇、 OC获取视频的第一帧图片thumbnailImage

    获取视频的第一帧图片 有时候我们拍摄完视频后,希望获取一张图片当作这个视频的介绍,这个图片thumbnailImage可以从视频的第一帧获取到. 我们的思路是先获取视频的URL,然后初始化一个MPMo ...

  2. 转---秒杀多线程第十二篇 多线程同步内功心法——PV操作上 (续)

    PV操作的核心就是 PV操作可以同时起到同步与互斥的作用. 1.同步就是通过P操作获取信号量,V操作释放信号量来进行. 2.互斥其实就是,同时操作P操作,结束后进行V操作即可做到. Java上实现PV ...

  3. 第五十二篇 Linux相关——数据库服务MySQL

        No.1. MySQL基本操作 CentOS7默认安装mariadb数据库,先将其移除 移除命令:sudo yum -y remove mariadb-libs.x86_64 下载MySQL源 ...

  4. 第五十二篇:webpack的loader(三) -url-loader (图片的loader)

    好家伙, 1.什么是base64? 图片的 base64 编码就是可以将一副图片数据编码成一串字符串,使用该字符串代替图像地址. 这样做有什么意义呢?我们知道,我们所看到的网页上的每一个图片,都是需要 ...

  5. 《手把手教你》系列技巧篇(五十二)-java+ selenium自动化测试-处理面包屑(详细教程)

    1.简介 面包屑(Breadcrumb),又称面包屑导航(BreadcrumbNavigation)这个概念来自童话故事"汉赛尔和格莱特",当汉赛尔和格莱特穿过森林时,不小心迷路了 ...

  6. Spring Cloud第十二篇 | 消息总线Bus

    ​ ​本文是Spring Cloud专栏的第十二篇文章,了解前十一篇文章内容有助于更好的理解本文: Spring Cloud第一篇 | Spring Cloud前言及其常用组件介绍概览 Spring ...

  7. 解剖SQLSERVER 第十二篇 OrcaMDF 行压缩支持(译)

    解剖SQLSERVER 第十二篇   OrcaMDF 行压缩支持(译) http://improve.dk/orcamdf-row-compression-support/ 在这两个月的断断续续的开发 ...

  8. 第十二篇 SQL Server代理多服务器管理

    本篇文章是SQL Server代理系列的第十二篇,详细内容请参考原文 在这一系列的上一篇,我们查看了维护计划,一个维护计划可能会创建多个作业,多个计划.你还简单地看了SSIS子系统,并查看了维护计划作 ...

  9. 第十二篇 Integration Services:高级日志记录

    本篇文章是Integration Services系列的第十二篇,详细内容请参考原文. 简介在前一篇文章我们配置了SSIS内置日志记录,演示了简单和高级日志配置,保存并查看日志配置,生成自定义日志消息 ...

随机推荐

  1. 【读书笔记】《C语言 从入门到精通》(第三版)笔记

    C语言,上学的时候都没学好,没想到现在却靠它吃饭.因为对C语言还是比较熟悉,所以买这本书是用来当"字典"用的.所以下面的笔记不会有很基础的内容. 1.书籍介绍 2.结构体 3.[C ...

  2. Java中最大的数据结构:LinkedHashMap了解一下?

    前言 Map 家族数量众多,其中 HashMap 和 ConcurrentHashMap 用的最多,而 LinkedHashMap 似乎则是不怎么用的,但是他却有着顺序.两种,一种是添加顺序,一种是访 ...

  3. 学习JDK源码(二):Integer

    最近没有好好保持学习的好习惯,该打. 天天忙,感觉都不知道在干嘛.真的厌倦了普通的Java代码,还是想学点新技术. 用了这么久的Java,最常用的数据类型肯定是Int了,而他的包装类Integer用的 ...

  4. Siamese network总结

    ​前言: 本文介绍了Siamese (连体)网络的主要特点.训练和测试Siamese网络的步骤.Siamese网络的应用场合.Siamese网络的优缺点.为什么Siamese被称为One-shot分类 ...

  5. 高性能的Redis数据结构小结

    一.概述 Redis 作为一种 KV 缓存服务器,有着极高的性能,相对于 Memcache,Redis 支持更多种数据类型,因此在业界应用广泛. 记得刚毕业那会参加面试,面试官会问我 Redis 为什 ...

  6. C++容器类插入和删除时迭代器的失效情况总结

    容器底层数据结构类型 包含的具体容器 内存分配特点 insert操作后迭代器失效情况 erase操作后迭代器失效情况 数组型数据结构 vector, string, deque, array 元素分配 ...

  7. 远程代码执行MS08-067漏洞复现失败过程

    远程代码执行MS08-067漏洞复现失败过程 漏洞描述: 如果用户在受影响的系统上收到特制的 RPC 请求,则该漏洞可能允许远程执行代码. 在微软服务器系统上,攻击者可能未经身份验证即可利用此漏洞运行 ...

  8. 05 jumpserver权限管理

    5.权限管理: 在同一个组下的用1户之间,资产是共享的. (1)为10.0.0.121_slavenode1资产授权: (2)为10.0.0.201_lc-pc资产授权: (3)查看授权列表:

  9. 41.1、shell编程案例

    1.案例1(表达式案例): 开发shell脚本分别实现以定义变量,脚本传参以及read读入的方式比较2个整数大小.用条件表达式(禁if) 进行判断并以屏幕输出的方式提醒用户比较结果: [root@ba ...

  10. 『心善渊』Selenium3.0基础 — 18、使用Selenium操作浏览器的弹窗

    目录 1.操作浏览器自带弹窗 2.操作浏览器页面自定义弹窗 1.操作浏览器自带弹窗 (1)说明: webdriver中处理JavaScript所生成的alert.confirm 以及prompt 弹窗 ...