OVERLAPPED I/O 非同步APC
阿新 • • 發佈:2018-12-18
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]; }