欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

APC (Asynchronous Procedure Call)

程序员文章站 2022-07-05 08:58:44
系统创建新线程时,会同时创建与这个线程相关联的队列,即异步过程调用(APC)的队列。 一些异步操作可以通过加入APC来实现,比如我现在学习的IO请求/完成。 IO完成时,系统向该线程的APC队列中加入一项,包含lpCompleteionRoutine和lpOverlapped。当线程处于非执行态且是 ......

系统创建新线程时,会同时创建与这个线程相关联的队列,即异步过程调用(apc)的队列。

一些异步操作可以通过加入apc来实现,比如我现在学习的io请求/完成。

bool readfileex(
  handle                          hfile,
  lpvoid                          lpbuffer,
  dword                           nnumberofbytestoread,
  lpoverlapped                    lpoverlapped,
  lpoverlapped_completion_routine lpcompletionroutine
);

io完成时,系统向该线程的apc队列中加入一项,包含lpcompleteionroutine和lpoverlapped。当线程处于非执行态且是可提醒的状态时,系统会取出apc中的项,并让线程执行其中的回调函数。这个动作会重复到队列空,我猜想可能还会被线程正常唤醒打断。

非执行态是线程调用了等待、休眠函数,像

dword sleepex(dword dwmilliseconds, bool balertable );
dword waitforsigleobjectex(handle hobject,dword dwmilliseconds,bool balertable);

balertable=true; 是可提醒状态!

另一段apc call的代码,是一个waitabletimer的例子。

#include <iostream>
#include<process.h>
#include<windows.h>
#include<tchar.h>
#include<string.h>
void apientry timerapcroutine(pvoid pvargtocompleteroutine, dword dwtimerlowvalue, dword dwtimerhighvalue);
void somefunc()
{
    handle htimer = createwaitabletimer(null, true, null);
    large_integer li = { 0 };
    setwaitabletimer(htimer, &li, 5000, timerapcroutine, null, false);
    sleepex(infinite, true);
    closehandle(htimer);
}
void apientry timerapcroutine(pvoid pvargtocompleteroutine, dword dwtimerlowvalue, dword dwtimerhighvalue)
{
    filetime ftutc, ftlocal;
    systemtime st;
    tchar szbuf[256];
    ftutc.dwhighdatetime = dwtimerhighvalue;
    ftutc.dwlowdatetime = dwtimerlowvalue;
    filetimetolocalfiletime(&ftutc, &ftlocal);
    filetimetosystemtime(&ftlocal, &st);
    getdateformat(locale_user_default, date_longdate, &st, null, szbuf, _countof(szbuf));
    _tcscat_s(szbuf, _countof(szbuf), " ");
    gettimeformat(locale_user_default, 0, &st, null, _tcschr(szbuf, text('\0')), (int)(_countof(szbuf) - _tcslen(szbuf)));
    messagebox(null, szbuf, text("timer went off at ..."), mb_ok);
}

int wmain(int argc, wchar_t* argv[])
{
    somefunc();
    char c;
    std::cin >> c;
    return 0;
}

 

 

线程跑到apc回调函数时,

APC (Asynchronous Procedure Call)

 

 

总结:

apc是由系统管理的与线程相关的队列,可用来执行异步操作。

apc的回调函数是在原线程休眠时在原线程上调用。