Windows编程-异步IO-2
如果进行多个ReadFile或者别的文件操作的函数,调用WaitForSingleObject等待的是句柄,所以没有办法鉴别是那一个文件操作函数执行完毕。
异步IO结构体-overlapped
typedef struct _OVERLAPPED {
ULONG_PTR Internal;
ULONG_PTR InternalHigh;
union {
struct {
DWORD Offset;
DWORD OffsetHigh;
} DUMMYSTRUCTNAME;
PVOID Pointer;
} DUMMYUNIONNAME;
HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED;
可以通过overlapped结构体中的hEvent事件来确定是那一个IO操作函数
利用hEvent来控制异步操作
CreateEvent()创建一个事件
HANDLE CreateEventA(
LPSECURITY_ATTRIBUTES lpEventAttributes,安全描述符
BOOL bManualReset,//如果此参数为TRUE,则该函数将创建一个手动重置的事件对象,该对象需要使用 ResetEvent函数将事件状态设置为非信号状态。如果此参数为FALSE,则该函数将创建一个自动重置事件对象,并且在释放单个等待线程之后,系统会自动将事件状态重置为非信号状态。
BOOL bInitialState,//如果此参数为TRUE,则表示事件对象的初始状态;否则,将显示事件对象的初始状态。否则,它是无信号的。
LPCSTR lpName//事件对象的名称。名称限制为 MAX_PATH个字符。名称比较区分大小写。
);
利用overlapped中的hEvent来控制异步操作
在创建overlapped结构体的时候就赋值一个hEvent,然后调用异步IO操作函数的时候赋值该结构体,等待的时候等待hEvent事件的消息就好了。
这样的好处是可以具体等待某一个操作的结束,如果对同一个句柄有多个操作就可以进行不同的处理
#include<Windows.h>
#include<iostream>
int main()
{
//1 打开文件
HANDLE hFile = CreateFile(L"test.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
//2 创建异步IO结构体
OVERLAPPED overlapped{ 0 };
overlapped.hEvent = CreateEvent(NULL,0,0,NULL);
//3 使用IO操作函数
CHAR buf[100] = { 0 };
ReadFile(hFile, buf, 100, NULL, &overlapped);
//4 等待异步IO执行完毕
DWORD Sum_Number;
WaitForSingleObject(hFile, -1);
return 0;
}
利用hEvent的缺点
利用hEvent由于不能在没完成的时候返回,使用了WaitForSingle会一直卡在这里就会等待它。所以也不太好
方法3-APC
每个线程都维护了一个APC(异步过程调用)队列,队列中的每一项都是函数,当一个线程处于可警醒(闲暇)状态时,线程会遍历自己的APC队列并调用所有函数,直到结束,再恢复执行。每当有一个异步IO请求完成时,ReadFileEx就会像APC队列中添加相应的函数和对应的参数,添加的顺序和投递的顺序不一定相同,那个先处理完就先投递那个。