一、queueuserapc概述
queueuserapc是Windows系統中常用的函數之一,用於異步執行一個回調函數,該函數採用的機制是向指定線程插入一個APC(Asynchronous Procedure Call)對象,使得該線程可以在特定的時機異步執行該函數,從而避免了線程等待和阻塞等問題,提高了系統的響應性。
二、queueuserapc函數說明
1、queueuserapc函數的定義
BOOL QueueUserAPC( PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData );
queueuserapc函數是Windows API中的一個函數,其定義在winbase.h頭文件中,主要參數包括回調函數指針pfnAPC,執行回調函數的線程句柄hThread和用戶自定義數據dwData。函數返回值為BOOL類型,返回執行結果。
2、queueuserapc函數的使用場景
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(); }
原創文章,作者:PFQPW,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/360382.html