#include "stdafx.h"
#include <windows.h>#include <iostream>using namespace std;
#define PAGE_SIZE 0x1000
void Sub_1(); //ReadFile 异步操作void Sub_2(); //ReadFileEx DWORD WINAPI Sub_1ThreadProcedure(LPVOID ParameterData);DWORD WINAPI Sub_2ThreadProcedure(LPVOID ParameterData);OVERLAPPED __Overlapped = { 0 };char __BufferData[4] = {0};int main()
{Sub_1();
//Sub_2();}void Sub_1(){ BOOL IsOk = FALSE; DWORD ReturnLength = 0; HANDLE FileHandle = CreateFile(L"ReadMe.txt", GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);//FILE_FLAG_OVERLAPPED很重要在异步 //有FILE_FLAG_OVERLAPPED系统就已经默认OverLapped了如果要同步必须删除 if (FileHandle == INVALID_HANDLE_VALUE) { int LastError = GetLastError(); goto Exit; }__Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); //绝对要创建 IRP那里看
if (__BufferData == NULL)
{ goto Exit; } IsOk = ReadFile(FileHandle, __BufferData, 4, &ReturnLength, &__Overlapped); //这里是通知IO要进行异步__Overlapped //接下来返回到线程,所以有Wait那一步,线程才会去执行 线程和当前进程无关 if (IsOk == FALSE) { int LastError = GetLastError();if (LastError == ERROR_IO_PENDING) { printf("ERROR_IO_PENDING\r\n"); } } HANDLE ThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Sub_1ThreadProcedure, (LPVOID)FileHandle, 0, NULL);
WaitForSingleObject(ThreadHandle, INFINITE);
Exit: if (FileHandle != NULL) { CloseHandle(FileHandle); FileHandle = NULL; } printf("\r\n"); return;}DWORD WINAPI Sub_1ThreadProcedure(LPVOID ParameterData){ HANDLE FileHandle = (HANDLE)ParameterData; BOOL IsOk = FALSE; DWORD ReturnLength = 0; while (1) { IsOk = WaitForSingleObject(__Overlapped.hEvent, INFINITE); IsOk -= WAIT_OBJECT_0; if (IsOk == 0) { IsOk = GetOverlappedResult(FileHandle, &__Overlapped, &ReturnLength, INFINITE);//ReturnLength读了多少字节if (IsOk==TRUE)
{ int i = 0; for (i = 0; i < ReturnLength; i++) { printf("%c", __BufferData[i]); } __Overlapped.Offset += ReturnLength;//这里是每次读写的起始位置,所以要加下去 ReadFile(FileHandle, &__BufferData, 4, &ReturnLength, &__Overlapped); } else { //数据完毕 break; } } else { return 0; } }return 0;
}void Sub_2()
{ BOOL IsOk = FALSE; HANDLE FileHandle = CreateFile(L"ReadMe.txt", GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (FileHandle == INVALID_HANDLE_VALUE) { int LastError = GetLastError(); goto Exit; } //__Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); //绝对不能提供该事件 HANDLE ThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Sub_2ThreadProcedure, (LPVOID)FileHandle, 0, NULL);if (__BufferData == NULL)
{ goto Exit; } IsOk = ReadFileEx(FileHandle, __BufferData, 4, &__Overlapped, NULL); if (IsOk == FALSE) { int LastError = GetLastError();if (LastError == ERROR_IO_PENDING)
{ //成功 } } WaitForSingleObject(ThreadHandle, INFINITE);Exit: if (FileHandle != NULL) { CloseHandle(FileHandle); FileHandle = NULL; } printf("\r\n"); return;}DWORD WINAPI Sub_2ThreadProcedure(LPVOID ParameterData)
{ HANDLE FileHandle = (HANDLE)ParameterData; DWORD ReturnLength = 0; BOOL IsOk = FALSE; while (1) { /*如果函数调用返回FALSE则可以用GetLastError来得到错误,如果返回成功则可以通过 lpNumberOfBytesTransferred参数来确定当前有多少数据已经被读或写。lpOverlapped 参数必须与调用ReadFile或WriteFile时使用同一个数据区。最后一个参数bWait表明是 否等待异步操作结束时才返回,如果设置为TRUE就可以等待文件读写完成时返回, 否则就会马上返回,利用这个特点可以利用它来等待异步文件操作的结束 (就如同等待事件变为有信号状态一样起到相同的作用)。*/ IsOk = GetOverlappedResult(FileHandle, &__Overlapped, &ReturnLength, TRUE); //IsOk = WaitForSingleObject(__Overlapped.hEvent, INFINITE); //?? 绝对不能这样做 if (IsOk == TRUE) { int i = 0; for (i = 0; i < ReturnLength; i++) { printf("%c", __BufferData[i]); }__Overlapped.Offset += ReturnLength;
ReadFileEx(FileHandle, &__BufferData, 4, &__Overlapped, NULL); } else { return 0; } }return 0;
}