一、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/n/360382.html