• APC (Asynchronous Procedure Call)


    系统创建新线程时,会同时创建与这个线程相关联的队列,即异步过程调用(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('')), (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是由系统管理的与线程相关的队列,可用来执行异步操作。

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

  • 相关阅读:
    asy for
    asy html !
    lib
    git clone 指定 version tag
    git tag
    git clone <url>--depth 、 git clone <url> --recursive
    xelatex CLI
    rsync
    curl options
    [转自]C语言offset_of宏和container_of宏
  • 原文地址:https://www.cnblogs.com/wyh1993/p/11666673.html
Copyright © 2020-2023  润新知