一、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();
}