一、queueuserapc概述
queueuserapc是Windows系统中常用的函数之一,用于异步执行一个回调函数,该函数采用的机制是向指定线程插入一个APC(Asynchronous Procedure Call)对象,使得该线程可以在特定的时机异步执行该函数,从而避免了线程等待和阻塞等问题,提高了系统的响应性。
二、queueuserapc函数说明
三、queueuserapc函数示例代码
1、使用queueuserapc实现线程通信
在下面的示例代码中,我们将演示通过使用queueuserapc函数实现线程间的通信。
首先,我们创建两个线程,一个线程用于发送消息,一个线程用于接收消息。我们将发送消息的线程的句柄作为参数传递给queueuserapc函数,在该函数中定义接收消息的回调函数进行消息的接收处理。
DWORD WINAPI ThreadProc1(LPVOID lpParam)
{
HANDLE hThread2 = (HANDLE)lpParam;
while (TRUE)
{
Sleep(1000);
QueueUserAPC((PAPCFUNC)APCFunc, hThread2, (ULONG_PTR)1);
}
return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpParam)
{
while (TRUE)
{
SleepEx(INFINITE, TRUE);
}
return 0;
}
void CALLBACK APCFunc(ULONG_PTR dwData)
{
printf("Thread 1 sends message to Thread 2\n");
}
2、使用queueuserapc异步执行函数
下面的示例代码演示了如何使用queueuserapc函数异步执行一个函数,以避免阻塞和等待。
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
while (TRUE)
{
SleepEx(INFINITE, TRUE);
}
return 0;
}
void CALLBACK APCFunc1(ULONG_PTR dwData)
{
printf("APC function 1 is called\n");
}
void CALLBACK APCFunc2(ULONG_PTR dwData)
{
printf("APC function 2 is called\n");
}
int main()
{
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, NULL, CREATE_SUSPENDED, NULL);
if (hThread == NULL)
{
return 0;
}
ResumeThread(hThread);
QueueUserAPC((PAPCFUNC)APCFunc1, hThread, (ULONG_PTR)1);
QueueUserAPC((PAPCFUNC)APCFunc2, hThread, (ULONG_PTR)2);
WaitForSingleObject(hThread, INFINITE);
return 0;
}
3、实现基于事件回调的框架
下面的示例代码演示了如何使用queueuserapc函数实现一个基于事件回调的框架。
#include
#include
#define WM_COMPLETE WM_APP+1
void CALLBACK APCFunc(ULONG_PTR dwData);
class EventFrame
{
public:
EventFrame(HWND hWnd) :m_hWnd(hWnd) {}
void OnComplete()
{
PostMessage(m_hWnd, WM_COMPLETE, 0, 0);
}
void Wait()
{
while (TRUE)
{
SleepEx(INFINITE, TRUE);
}
}
private:
HWND m_hWnd;
};
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMPLETE:
printf("WM_COMPLETE\n");
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
TCHAR szClassName[] = _T("Sample Window Class");
MSG msg = { 0 };
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(WNDCLASSEX);
wc.hInstance = hInstance;
wc.lpszClassName = szClassName;
wc.lpfnWndProc = WndProc;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
HWND hWnd = CreateWindowEx(
WS_EX_APPWINDOW, szClassName, _T("Sample Window"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
HWND_DESKTOP, NULL, hInstance, NULL);
if (hWnd == NULL)
{
return 0;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
EventFrame frame(hWnd);
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)APCFunc, (LPVOID)&frame, CREATE_SUSPENDED, NULL);
if (hThread == NULL)
{
return 0;
}
ResumeThread(hThread);
frame.Wait();
return msg.wParam;
}
void CALLBACK APCFunc(ULONG_PTR dwData)
{
EventFrame* pFrame = (EventFrame*)dwData;
pFrame->OnComplete();
}