C++第五十二篇 -- 多线程之消息传递
主线程向子线程发送消息
参考链接: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++第五十二篇 -- 多线程之消息传递的更多相关文章
- 第五十二篇、 OC获取视频的第一帧图片thumbnailImage
获取视频的第一帧图片 有时候我们拍摄完视频后,希望获取一张图片当作这个视频的介绍,这个图片thumbnailImage可以从视频的第一帧获取到. 我们的思路是先获取视频的URL,然后初始化一个MPMo ...
- 转---秒杀多线程第十二篇 多线程同步内功心法——PV操作上 (续)
PV操作的核心就是 PV操作可以同时起到同步与互斥的作用. 1.同步就是通过P操作获取信号量,V操作释放信号量来进行. 2.互斥其实就是,同时操作P操作,结束后进行V操作即可做到. Java上实现PV ...
- 第五十二篇 Linux相关——数据库服务MySQL
No.1. MySQL基本操作 CentOS7默认安装mariadb数据库,先将其移除 移除命令:sudo yum -y remove mariadb-libs.x86_64 下载MySQL源 ...
- 第五十二篇:webpack的loader(三) -url-loader (图片的loader)
好家伙, 1.什么是base64? 图片的 base64 编码就是可以将一副图片数据编码成一串字符串,使用该字符串代替图像地址. 这样做有什么意义呢?我们知道,我们所看到的网页上的每一个图片,都是需要 ...
- 《手把手教你》系列技巧篇(五十二)-java+ selenium自动化测试-处理面包屑(详细教程)
1.简介 面包屑(Breadcrumb),又称面包屑导航(BreadcrumbNavigation)这个概念来自童话故事"汉赛尔和格莱特",当汉赛尔和格莱特穿过森林时,不小心迷路了 ...
- Spring Cloud第十二篇 | 消息总线Bus
本文是Spring Cloud专栏的第十二篇文章,了解前十一篇文章内容有助于更好的理解本文: Spring Cloud第一篇 | Spring Cloud前言及其常用组件介绍概览 Spring ...
- 解剖SQLSERVER 第十二篇 OrcaMDF 行压缩支持(译)
解剖SQLSERVER 第十二篇 OrcaMDF 行压缩支持(译) http://improve.dk/orcamdf-row-compression-support/ 在这两个月的断断续续的开发 ...
- 第十二篇 SQL Server代理多服务器管理
本篇文章是SQL Server代理系列的第十二篇,详细内容请参考原文 在这一系列的上一篇,我们查看了维护计划,一个维护计划可能会创建多个作业,多个计划.你还简单地看了SSIS子系统,并查看了维护计划作 ...
- 第十二篇 Integration Services:高级日志记录
本篇文章是Integration Services系列的第十二篇,详细内容请参考原文. 简介在前一篇文章我们配置了SSIS内置日志记录,演示了简单和高级日志配置,保存并查看日志配置,生成自定义日志消息 ...
随机推荐
- 【读书笔记】《C语言 从入门到精通》(第三版)笔记
C语言,上学的时候都没学好,没想到现在却靠它吃饭.因为对C语言还是比较熟悉,所以买这本书是用来当"字典"用的.所以下面的笔记不会有很基础的内容. 1.书籍介绍 2.结构体 3.[C ...
- Java中最大的数据结构:LinkedHashMap了解一下?
前言 Map 家族数量众多,其中 HashMap 和 ConcurrentHashMap 用的最多,而 LinkedHashMap 似乎则是不怎么用的,但是他却有着顺序.两种,一种是添加顺序,一种是访 ...
- 学习JDK源码(二):Integer
最近没有好好保持学习的好习惯,该打. 天天忙,感觉都不知道在干嘛.真的厌倦了普通的Java代码,还是想学点新技术. 用了这么久的Java,最常用的数据类型肯定是Int了,而他的包装类Integer用的 ...
- Siamese network总结
前言: 本文介绍了Siamese (连体)网络的主要特点.训练和测试Siamese网络的步骤.Siamese网络的应用场合.Siamese网络的优缺点.为什么Siamese被称为One-shot分类 ...
- 高性能的Redis数据结构小结
一.概述 Redis 作为一种 KV 缓存服务器,有着极高的性能,相对于 Memcache,Redis 支持更多种数据类型,因此在业界应用广泛. 记得刚毕业那会参加面试,面试官会问我 Redis 为什 ...
- C++容器类插入和删除时迭代器的失效情况总结
容器底层数据结构类型 包含的具体容器 内存分配特点 insert操作后迭代器失效情况 erase操作后迭代器失效情况 数组型数据结构 vector, string, deque, array 元素分配 ...
- 远程代码执行MS08-067漏洞复现失败过程
远程代码执行MS08-067漏洞复现失败过程 漏洞描述: 如果用户在受影响的系统上收到特制的 RPC 请求,则该漏洞可能允许远程执行代码. 在微软服务器系统上,攻击者可能未经身份验证即可利用此漏洞运行 ...
- 05 jumpserver权限管理
5.权限管理: 在同一个组下的用1户之间,资产是共享的. (1)为10.0.0.121_slavenode1资产授权: (2)为10.0.0.201_lc-pc资产授权: (3)查看授权列表:
- 41.1、shell编程案例
1.案例1(表达式案例): 开发shell脚本分别实现以定义变量,脚本传参以及read读入的方式比较2个整数大小.用条件表达式(禁if) 进行判断并以屏幕输出的方式提醒用户比较结果: [root@ba ...
- 『心善渊』Selenium3.0基础 — 18、使用Selenium操作浏览器的弹窗
目录 1.操作浏览器自带弹窗 2.操作浏览器页面自定义弹窗 1.操作浏览器自带弹窗 (1)说明: webdriver中处理JavaScript所生成的alert.confirm 以及prompt 弹窗 ...