请选择 进入手机版 | 继续访问电脑版

硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1229|回复: 0
收起左侧

异步读写(ReadFileEx和ReadFile)之overlapped

[复制链接]

747

主题

1048

回帖

3294

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3294
发表于 2021-1-3 02:21:29 | 显示全部楼层 |阅读模式
原文: https://www.cnblogs.com/L-Sunny/p/8389388.html

ReadFile异步操作.C (4.67 KB, 下载次数: 1)

#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);
        }
        __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);
      }
      
      __Overlapped.Offset += ReturnLength;
      ReadFileEx(FileHandle, &__BufferData, 4, &__Overlapped, NULL);
    }
    else
    {
      return 0;
    }
  }
  
  return 0;
}


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-3-29 20:41 , Processed in 0.152522 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表