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

以前对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,00,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, 
00);
    
return res;
}

主线程调用Initialize来创建APCWnd,以及保存主线程句柄。为了使APC能够及时响应创建APCWnd,工作者线程调用CallFunctionAsync让主线程运行 func函数指针指向的函数,在该函数中向APCWnd发送WM_NULL消息,窗口过程在响应该消息时调用SleepEx使线程进入警告状态,从而检查并调用APC队列中的APC函数。这样就实现了一个让已知的线程调用指定的函数。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值