Worker线程使用消息循环

这个示例代码展示了如何在Win32环境中创建一个带有自己消息队列但没有窗口的worker线程。主线程通过PostThreadMessage发送WM_JOB_开头的消息,worker线程根据消息类型进行不同操作,如正向打印、反向打印和转换为小写等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
 * Worker.cpp
 *
 * Sample code for "Multithreading Applications in Win32"
 * This is from Chapter 14, Listing 14-3
 *
 * Demonstrate using worker threads that have
 * their own message queue but no window.
 */
 
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <process.h>
#include <string.h>
#include "MtVerify.h"

unsigned WINAPI ThreadFunc(void* p);

HANDLE ghEvent;

#define WM_JOB_PRINT_AS_IS          WM_APP + 0x0001
#define WM_JOB_PRINT_REVERSE        WM_APP + 0x0002
#define WM_JOB_PRINT_LOWER          WM_APP + 0x0003
#define WM_LEIWEI					WM_APP + 0x0004
int main(VOID) 
{ 
    HANDLE hThread;
    unsigned tid;

    // Give the new thread something to talk
    // to us with.

	//创建手动事件

    ghEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	unsigned CurrentId = GetCurrentThreadId();

	UNREFERENCED_PARAMETER(CurrentId);

    hThread = (HANDLE)_beginthreadex(NULL,
                      0,
                      ThreadFunc,
                      0,
                      0,
                      &tid );
    MTVERIFY(hThread);

    // This thread has to wait for the new thread
    // to init its globals and msg queue.
    WaitForSingleObject(ghEvent, INFINITE);//等待事件有信号

    // The only place in the book we get to use
    // the thread ID!
	//strdup 调用的是malloc所以需要free
    char *szText = strdup("Thank you for buying this book.\n");
    PostThreadMessage(tid, WM_JOB_PRINT_AS_IS, NULL, (LPARAM)szText);

    szText = strdup("Text is easier to read forward.\n");
    PostThreadMessage(tid, WM_JOB_PRINT_REVERSE, NULL, (LPARAM)szText);

    szText = strdup("\nLOWER CASE IS FOR WHISPERING.\n");
    PostThreadMessage(tid, WM_JOB_PRINT_LOWER, NULL, (LPARAM)szText);

	Sleep(4000);

	//给线程发消息,退出
	PostThreadMessage(tid,WM_QUIT,0,0);

    WaitForSingleObject(hThread, INFINITE);//等待线程退出,然后关闭句柄

    CloseHandle(hThread);

	system("pause");

    return 0;
}
 
VOID CALLBACK TimerFunc(
    HWND hwnd,  // handle of window for timer messages 
    UINT uMsg,  // WM_TIMER message
    UINT idEvent,   // timer identifier
    DWORD dwTime )  // current system time
{
	//取消编译器的警告,没有引用的变量
    UNREFERENCED_PARAMETER(hwnd);
    UNREFERENCED_PARAMETER(uMsg);
	printf("onTimer function\n");

  //  PostThreadMessage(GetCurrentThreadId(), WM_QUIT,0,0);
	unsigned id = GetCurrentThreadId();

	PostThreadMessage(id, WM_LEIWEI,0,0);
}
 
/*
 * Call a function to do something that terminates
 * the thread with ExitThread instead of returning.
 */
unsigned WINAPI ThreadFunc(LPVOID n)
{
    UNREFERENCED_PARAMETER(n);

    MSG msg;

    // This creates the message queue.
	//创建一个消息队列
    PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);

	//设置事件有激活
    SetEvent(ghEvent);

    // We'll run for two seconds
    SetTimer(NULL, NULL, 500, (TIMERPROC)TimerFunc);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        char *psz = (char *)msg.lParam;
        switch(msg.message)
        {
        case WM_JOB_PRINT_AS_IS:
            printf("%s", psz);
            free(psz);
            break;
        case WM_JOB_PRINT_REVERSE:
            printf("%s", strrev(psz));
            free(psz);
            break;
        case WM_JOB_PRINT_LOWER:
            printf("%s", _strlwr(psz));
            free(psz);
            break;
		case WM_LEIWEI:
			printf("timer:............\n");
			break;
        default:
			printf("message id=%0X\n",msg.message);
            DispatchMessage(&msg);
        }
    }

    return 0;
}


GUI线程Worker线程是常见的多线程编程模型,用于实现图形用户界面(GUI)应用程序的并发处理。 1. GUI线程(也称为主线程):GUI线程负责处理用户界面的绘制、响应用户输入等任务。在大多数GUI框架中,GUI线程也是事件循环线程,负责监听和分发用户事件(如鼠标点击、键盘输入)并对其作出相应的响应。在这种模型下,GUI线程通常是单线程的,意味着在GUI线程中执行的任何耗时操作都会导致界面冻结,造成用户体验下降。 2. Worker线程Worker线程用于执行耗时的任务,以避免在GUI线程中阻塞。这些任务可以是计算密集型的操作,如图像处理、数据分析等,也可以是I/O密集型的操作,如文件读写、网络请求等。通过将这些任务放在Worker线程中执行,可以保持GUI线程的响应性,使用户能够继续与界面进行交互。 在实际开发中,通常采用以下方式来实现GUI线程Worker线程的协同工作: 1. 任务分发:GUI线程接收用户事件,并将耗时任务委托给Worker线程处理。这可以通过消息队列、事件驱动等机制来实现,GUI线程将任务放入队列中,Worker线程从队列中取出任务并执行。 2. 线程间通信:GUI线程Worker线程之间需要进行数据交换和同步。常见的线程间通信方式包括使用线程安全的队列、事件、互斥锁、条件变量等机制。 3. 界面更新:在Worker线程执行完耗时任务后,需要将结果返回给GUI线程,并更新界面显示。通常可以通过回调函数、信号槽机制等方式来实现。 需要注意的是,在多线程编程中,要注意线程安全性和资源管理,避免竞态条件、死锁等问题的发生。此外,对于一些特殊的操作,如对GUI组件的修改,可能需要在GUI线程中执行,以避免跨线程访问的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值