您的位置:首页 > 其它

用户模式异步过程调用(APC)

2007-10-18 17:47 369 查看
以前对User-Mode APC不甚了解, 最近在看一个开源项目时看到了对APC的使用。看来多看代码的确是有好处地:)废话不多说。我们来看看APC的真面目吧。

APC即asynchronous procedure call,每一线程都有一个APC队列。操作系统 允许一个应用向一个指定线程的APC队列中放入APC函数。当指定的线程处于警告状态时,该线程就会调用队列中的APC函数。调用的顺序为先入先出(FIFO)。可以用以下函数使一个线程进入警告状态:

SleepEx, SignalObjectAndWait, WaitForSingleObjectEx, WaitForMultipleObjectsEx, MsgWaitForMultipleObjectsEx

一句话,就是可以让别的线程执行一个函数。下面是一段例子


LRESULT CALLBACK APCWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)


{


if (msg==WM_NULL) SleepEx(0,TRUE);


return DefWindowProc(hwnd,msg,wParam,lParam);


}




//主线程调用


BOOL Initialize()


{


DuplicateHandle(GetCurrentProcess(),


GetCurrentThread(),


GetCurrentProcess(),


&g_hMainThread,


THREAD_SET_CONTEXT,


FALSE,


0);


//为了让APC尽快响应,创建窗口,在WM_NULL中调用SleepEx让线程进入警告状态。


g_hAPCWnd = CreateWindowEx(0,_T("STATIC"),NULL,0, 0,0,0,0, NULL,NULL,NULL,NULL);


SetWindowLongPtr(m_hACPWnd, GWL_WNDPROC, (LONG)(LONG_PTR)APCWndProc);


return TRUE;


}




//工作者线程调用


int CallFunctionAsync(void (__stdcall *func)(void *), void *arg)


{


int res = 0;


res = QueueUserAPC((void (__stdcall *)(DWORD))func, g_hMainThread, (DWORD_PTR)arg);


PostMessage(g_hAPCWnd, WM_NULL, 0, 0);


return res;


}

主线程调用Initialize来创建APCWnd,以及保存主线程句柄。为了使APC能够及时响应创建APCWnd,工作者线程调用CallFunctionAsync让主线程运行 func函数指针指向的函数,在该函数中向APCWnd发送WM_NULL消息,窗口过程在响应该消息时调用SleepEx使线程进入警告状态,从而检查并调用APC队列中的APC函数。这样就实现了一个让已知的线程调用指定的函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: