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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// 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库,前面有讲过这一章节内容。