1. 程式人生 > 其它 >C++第五十二篇 -- 多執行緒之訊息傳遞

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();
}
View Code

這個程式起源於建立一個Dll帶MFC庫,前面有講過這一章節內容。