When the system creates a new thread, and this will also create a queue associated with the thread that an asynchronous procedure call (APC) queue.
Some asynchronous operation can be achieved by adding APC, for example, I now learn the IO request / completion.
BOOL ReadFileEx(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPOVERLAPPED lpOverlapped,
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
When the IO completion, the APC system queue is added to a thread, and comprising lpCompleteionRoutine lpOverlapped. When a thread is in a state of non-execution state is alert and the system will remove the entry in the APC, and wherein a thread of execution so that the callback function. This action is repeated until the queue is empty, I guess the thread may also be interrupted normal wake.
Non-execution states are thread calls wait, sleep function, like
DWORD SleepEx(DWORD dwMilliseconds, bool bAlertable );
DWORD WaitForSigleObjectEx(HANDLE hObject,DWORD dwMilliseconds,bool bAlertable);
bAlertable = true; alert status is!
APC call another piece of code, it is an example of a 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; }
When the thread ran APC callback function,
to sum up:
APC is a queue management system associated with the threads, it can be used to perform asynchronous operations.
APC callback function is invoked in the original thread in the original thread to sleep.