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库,前面有讲过这一章节内容。

 

posted @ 2021-06-19 13:55  o云淡风轻o  阅读(1338)  评论(1编辑  收藏  举报