一、queueuserapc概述
queueuserapc是Windows系統(tǒng)中常用的函數(shù)之一,用于異步執(zhí)行一個(gè)回調(diào)函數(shù),該函數(shù)采用的機(jī)制是向指定線程插入一個(gè)APC(Asynchronous Procedure Call)對(duì)象,使得該線程可以在特定的時(shí)機(jī)異步執(zhí)行該函數(shù),從而避免了線程等待和阻塞等問(wèn)題,提高了系統(tǒng)的響應(yīng)性。
二、queueuserapc函數(shù)說(shuō)明
三、queueuserapc函數(shù)示例代碼
1、使用queueuserapc實(shí)現(xiàn)線程通信
在下面的示例代碼中,我們將演示通過(guò)使用queueuserapc函數(shù)實(shí)現(xiàn)線程間的通信。
首先,我們創(chuàng)建兩個(gè)線程,一個(gè)線程用于發(fā)送消息,一個(gè)線程用于接收消息。我們將發(fā)送消息的線程的句柄作為參數(shù)傳遞給queueuserapc函數(shù),在該函數(shù)中定義接收消息的回調(diào)函數(shù)進(jìn)行消息的接收處理。
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異步執(zhí)行函數(shù)
下面的示例代碼演示了如何使用queueuserapc函數(shù)異步執(zhí)行一個(gè)函數(shù),以避免阻塞和等待。
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、實(shí)現(xiàn)基于事件回調(diào)的框架
下面的示例代碼演示了如何使用queueuserapc函數(shù)實(shí)現(xiàn)一個(gè)基于事件回調(diào)的框架。
#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();
}