#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;
}
