您的位置:首页 > 其它

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

2013-05-26 16:12 253 查看
以前对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函数。这样就实现了一个让已知的线程调用指定的函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: