C++第五十二篇 -- 多執行緒之訊息傳遞
阿新 • • 發佈:2021-06-19
主執行緒向子執行緒傳送訊息
參考連結: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(); }View Code
這個程式起源於建立一個Dll帶MFC庫,前面有講過這一章節內容。