APC队列
#include <stdio.h>
#include <windows.h>
// 保存 IO 操作的结果
CHAR Buffer1[10] = { 0 };
CHAR Buffer2[10] = { 0 };
// APC: 在线程处于闲暇状态才会调用
VOID WINAPI OverLappendRoutine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
{
// 1. 每一个线程都有一个 APC 队列,其中保存的是一些
// 函数,这些函数会在线程处于[可警醒](闲暇)状态时
// 被依次队列,知道所有函数调用结束
// 2. 每当有一个 IO 请求被完成的时候,就会向 APC 队列
// 中添加一个函数并指定对应的参数,添加函数的顺序和
// IO 请求提交的顺序并不一定相同。
// 判断当前的 IO 请求是谁产生的
if (lpOverlapped->hEvent == (HANDLE)0x1)
printf("[%d]: %s", 1, Buffer1);
else
printf("[%d]: %s", 2, Buffer2);
}
int main()
{
// 1. 以重叠 IO 的方式打开一个文件
HANDLE FileHandle = CreateFile(L"test.txt", GENERIC_ALL,
NULL, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
// 2. 投递第一个 IO 请求,读取 [3 ~ 6] 的字符,使用 Ex 版本的函数,需要提供回调函数
OVERLAPPED OverLapped1 = { 0 };
OverLapped1.Offset = 3;
OverLapped1.hEvent = (HANDLE)0x1; // 用于识别是哪一个 IO 请求
ReadFileEx(FileHandle, Buffer1, 4, &OverLapped1, OverLappendRoutine);
// 3. 投递第二个 IO 请求,读取 [0 ~ 2] 的字符,初始化一个事件对象
OVERLAPPED OverLapped2 = { 0 };
OverLapped2.hEvent = (HANDLE)0x2; // 用于识别是哪一个 IO 请求
ReadFileEx(FileHandle, Buffer2, 3, &OverLapped2, OverLappendRoutine);
// 使用各种等待函数的 Ex 版本设置闲暇状态
SleepEx(0, TRUE);
return 0;
}