多线程编程中的API使用技巧

多线程编程的领域中,经常会遇到各种挑战和问题。其中之一就是如何有效地在工作线程中使用消息循环。本文将介绍一个经常被忽视但非常有用的API——PostThreadMessage,以及如何在工作线程中实现消息循环。

PostThreadMessage的使用

在多年的多线程编程经验中,一直在思考PostThreadMessage的用途。尽管曾在UI线程中使用过它,但想知道它是否可以在工作线程中使用。相信每个API都有其存在的价值,否则微软的程序员们不会提供无用的功能。因此,创建了一个测试程序,在工作线程中加入了一个消息循环,并传递了NULL作为HWND参数:

#include <windows.h> DWORD threadProc(LPVOID lParam) { MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { if (msg.message == WM_APP+1) { MessageBoxA(NULL, "Hello", "From Thread", MB_OK); } DispatchMessage(&msg); } MessageBoxA(NULL, "Thread will close on pressing OK", "From Thread", MB_OK); return 0; } int main() { DWORD m_idThread; CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadProc, NULL, 0, &m_idThread); PostThreadMessage(m_idThread, WM_APP+1, 0, 0); PostThreadMessage(m_idThread, WM_QUIT, 0, 0); return 0; }

这段代码展示了如何在工作线程中使用GetMessage和DispatchMessage来处理消息。GetMessage函数可以获取当前线程的消息,无论是窗口消息还是线程消息。

MSDN文档中提到:“如果hWnd为NULL,GetMessage将检索当前线程的任何窗口的消息,以及当前线程的消息队列中hwnd值为NULL的消息(参见MSG结构)。因此,如果hWnd为NULL,GetMessage将处理窗口消息和线程消息。”

消息循环中,添加了一个消息处理器,它会等待特定的线程消息(例如WM_APP+1),然后执行一些操作,否则它将继续执行其工作。

PostThreadMessage的工作原理

PostThreadMessage API通过线程ID而不是窗口句柄(HWND)来工作。以下是MSDN文档中关于PostThreadMessage的描述:“将消息发送到指定线程的消息队列。它在不等待线程处理消息的情况下返回。”

BOOL WINAPI PostThreadMessage( __in DWORD idThread, __in UINT Msg, __in WPARAM wParam, __in LPARAM lParam );

要获取线程ID,需要在创建线程时通过引用传递一个DWORD变量来收集新创建的工作线程的线程ID,如下所示:

DWORD m_idThread; CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadProc, NULL, 0, &m_idThread);

同样,在_beginthreadex()API中也可以这样做,但是在_beginthread() API中没有这样的安排来检索线程ID。尽管有其他方法,但这里不讨论,因为这是离题的。现在有了工作线程的线程ID,可以使用PostThreadMessage向线程发送消息,例如发送一个问候:

PostThreadMessage(m_idThread, WM_APP+1, 0, 0);

以及指示线程退出:

PostThreadMessage(m_idThread, WM_QUIT, 0, 0);
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485