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内置日志记录,演示了简单和高级日志配置,保存并查看日志配置,生成自定义日志消息 ...
随机推荐
- P1045 [NOIP2003 普及组] 麦森数
题目描述 形如2^P−1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2^P−1不一定也是素数. 到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377, ...
- [源码解析] 深度学习分布式训练框架 horovod (3) --- Horovodrun背后做了什么
[源码解析] 深度学习分布式训练框架 horovod (3) --- Horovodrun背后做了什么 目录 [源码解析] 深度学习分布式训练框架 horovod (3) --- Horovodrun ...
- 【模拟7.16】通讯(tarjan缩点加拓扑排序)
这题确实水,纯板子,考试意外出错,只拿了暴力分QAQ tarjan缩点加上拓扑排序,注意这里求最短路径时不能用最小生成树 因为是单向边,不然就可能不是一个联通图了.... 1 #include< ...
- 把新建的vue项目上传到码云
1:在码云上建一个仓库(使用Readme文件初始化这个项目的勾取消掉) 2:在项目文件中打开git命令窗口(如下图),命令git init 初始化git仓库 运行之后有一个.git文件夹 现在用vsc ...
- 浅析C++的函数式编程
前言 Java8在Java中通过lambda表达式.Stream API引入了函数式编程,那么C++中是否也支持函数式编程呢?答案是肯定的.目前关于C++进行函数式编程的语法探究的相关博客.文章并不多 ...
- Go基础语法0x01-数组
数组 1.Go数组简介 数组是Go语言编程中最常用的数据结构之一.顾名思义,数组就是指一系列同一类型数据的集合.数组中包含的每个数据被称为数组元素(element),一个数组包含的元素个数被称为数组的 ...
- Jenkins CI&CD 自动化发布项目实战(上篇)
Jenkins CI&CD 自动化发布项目实战(上篇) 作者 刘畅 时间 2020-11-28 实验环境 centos7.5 主机名 ip 服务配置 软件 gitlab 172.16.1.71 ...
- 49、django工程(cookie+session)
49.1.介绍: 1.cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要"保持状态",因此cookie就是在这样一个场景下诞生. cooki ...
- 基于Redis的分布式锁设计
前言 基于Redis的分布式锁实现,原理很简单嘛:检测一下Key是否存在,不存在则Set Key,加锁成功,存在则加锁失败.对吗?这么简单吗? 如果你真这么想,那么你真的需要好好听我讲一下了.接下来, ...
- 8、SpringBoot整合之SpringBoot整合MongoDB
SpringBoot整合MongoDB 一.创建项目,选择依赖 仅选择Spring Web.Spring Data MongoDB即可 二.引入相关依赖(非必要) 这里只是为了实体类的创建方便而引入l ...