OVERLAPPED I/O 异步APC

版权声明: https://blog.csdn.net/dashoumeixi/article/details/83514879

APC简介:APC

第一个例子. 第二个例子使用APC 来解决一些问题

/*
   首先使用 OVERLAPPED  结构, 其中有Event 对象, 可用可不用,这个例子先不用

   CreateFile 其中一个参数使用 FILE_FLAG_OVERLAPPED 
    
   ReadFile  默认同步, 在最后一个参数使用 OVERLAPPED  ;
   ReadFile  返回TRUE ,则代表已经读完了
             否则应该检查 GetLastError , 系统是否为此安排了等待.

   如果 GetLastError == ERROR_IO_PENDING ,则成功了, 等着取数据, 否则失败

   之后可以使用 GetOverlappedResult(最后一个参数为TRUE) / WaitForSingObject 来等待直到完成;
   
    
*/


void read_overlapped(const TCHAR * path)
{
    //这里没有使用其中的 Event 对象. 
    OVERLAPPED overlap = {0};
    DWORD bytesReaded = 0;
    BOOL ret = FALSE;
    char * buf = new char[8196 * 10];

    // 注意:FILE_FLAG_OVERLAPPED 

    HANDLE hFile = CreateFile(path,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);
    if(INVALID_HANDLE_VALUE == hFile){
        cout << "INVALID_HANDLE_VALUE" << endl;
        return;
     }

    //从哪开始读文件 
    overlap.Offset = 0;

    //注意overlap 需要传入
    ret = ReadFile(hFile,buf,8196*10,&bytesReaded
                    ,&overlap);

    //直接就完成了, 您的计算机硬盘可真快
    if(ret){
        cout << "done :" <<  bytesReaded << endl;
        cout << buf << endl;
    }
    else
    {
        //检测一下错误, 确认是否已经进入准备状态
        DWORD err = GetLastError();

        //ok
        if(ERROR_IO_PENDING == err )
        {
            

            //GetOverlappedResult(hFile,&overlap,&bytesReaded,TRUE); 相当于WaitForSingObject
            //这样其实不太好 , 浪费cpu.
            while(1){
                cout << "LOADing: " << GetLastError() << endl;
                 ret = GetOverlappedResult(hFile,&overlap,&bytesReaded,FALSE);
                 if(ret){
                     cout << "ret:" << ret << ",bytesread:" << bytesReaded << endl;
                     break;
                 }
            }
        }
        else
        {
            cout << "err : " << err << endl;
        }
    }
    CloseHandle(hFile);
}

通过OVERLAPPED 中的事件对象,对同一个文件读取多次 . 

void read_overlapped2(const TCHAR * path)
{
    HANDLE event_handles[2];
    OVERLAPPED overlap[2] = {0};
    char * buf[2] = {0};
    DWORD  num = 0;
    HANDLE hFile = CreateFile(path,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);
    if(INVALID_HANDLE_VALUE == hFile){
        cout << "INVALID_HANDLE_VALUE" << endl;
        return;
     }

    BOOL ret = 0;
    int success_len = 0;
    for(int i = 0; i < 2; ++i){
        event_handles[i] = CreateEvent(0,TRUE,FALSE,NULL);
        overlap[i].hEvent = event_handles[i];
        overlap[i].Offset = i*1000 + i;
        buf[i] = new char[8196 * 1024];
        ret = ReadFile(hFile,buf[i],8196 +overlap[i].Offset  ,&num,&overlap[i]);
        if(ret){
            cout << "index:" << i << ", is done" << endl;
            cout << "index:" << i << ",num:" << num;
            cout << "index:" << i << buf[i] << endl;
            ++success_len;
        }
        else {
            if(GetLastError() != ERROR_IO_PENDING){
                    cout << "index:" << i << "failed" << endl;
                    delete[] buf[i];
                    SetEvent(event_handles[i]);
            }
            else {
                ++success_len;
            }
        }
    }
    cout << "success_len:" << success_len << endl;
    WaitForMultipleObjects(success_len,event_handles,TRUE,-1);
    ret = GetOverlappedResult(hFile,&overlap[0],&num,FALSE);
    cout << "ret:" << ret << ", num:" << num << endl;
    ret = GetOverlappedResult(hFile,&overlap[1],&num,FALSE);
    cout << "ret:" << ret << ", num:" << num << endl;
    CloseHandle(hFile);

}

使用ReadFileEx APC:

const int count = 2;
HANDLE event_io;
void CALLBACK ioCompletionRoutine(
	_In_    DWORD        dwErrorCode,
	_In_    DWORD        dwNumberOfBytesTransfered,
	_Inout_ LPOVERLAPPED lpOverlapped
	)
{
	int index = (int)lpOverlapped->hEvent;
	printf("index : %d , readbytes: %d ,err:%d\n", index, dwNumberOfBytesTransfered, dwErrorCode);
	if (++index == count){
		SetEvent(event_io);
	}
}

void test_readfileex(const TCHAR * path)
{
	event_io = CreateEvent(0, TRUE, FALSE, 0);
	const int bufsize = 2 << 13;
	HANDLE hFile =CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
		FILE_FLAG_OVERLAPPED, NULL);
	if (INVALID_HANDLE_VALUE == hFile){
		printf("createfile failed");
		return;
	}

	OVERLAPPED overlap[count] = { 0 };
	TCHAR* buf[count] = { 0 };
	DWORD ret = 0 , err = 0;
	for (int i = 0; i <count; ++i){
		overlap[i].hEvent = (HANDLE)i;
		overlap[i].Offset = i *bufsize + i;
		buf[i] = new TCHAR[bufsize];
		ret = ReadFileEx(hFile, buf[i], bufsize, &overlap[i], ioCompletionRoutine);
		err = GetLastError();
		printf("ret:%d, err:%d\n", ret, err);
		if (!ret){
			// 出错了 
		}
	}
	while (1){ 
		//注意是带ex结尾的 . 这里将阻塞ioCompletionRoutine 完成后将返回一次,所以需要判断
		ret = WaitForSingleObjectEx(event_io, -1, TRUE);
		if (WAIT_OBJECT_0 == ret)
			break;
		else
			printf("WaitForSingleObjectEx return :%d\n", ret);
	}

	CloseHandle(hFile);
	CloseHandle(event_io);
	for (int i = 0; i < count; ++i)
		delete[] buf[i];
}

猜你喜欢

转载自blog.csdn.net/dashoumeixi/article/details/83514879