- 觸發裝置核心對象
缺點:同一個裝置核心對象有可能進行多次讀寫操作,這樣第一個完成這個裝置核心對象就會被觸發,所以這種方式不可以使用於這種情形
void Test1(){ HANDLE hFile = ::CreateFile(_T("aaa.txt"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if(!hFile) { wcout<<L"CreateFile Failed ErroCode:"<<::GetLastError()<<endl; return ; } DWORD dwFileSize = ::GetFileSize(hFile,0); wcout<<L"FileSize:"<<dwFileSize<<endl; char * pFileContent = new char[10000000]; DWORD dwReaded = 0; OVERLAPPED o_Read = {0}; DWORD bReadDone = ::ReadFile(hFile, pFileContent, 10000000, &dwReaded, &o_Read); DWORD dwError = ::GetLastError(); if(!bReadDone && (dwError == ERROR_IO_PENDING)) { WaitForSingleObject(hFile,INFINITE); bReadDone = TRUE; } if(bReadDone) wcout<<L"I/O Code:"<<o_Read.Internal<<" TransedBytes:"<<o_Read.InternalHigh<<endl; else wcout<<"Error:"<<::GetLastError()<<endl; ::CloseHandle(hFile); delete [] pFileContent;}
- 觸發事件核心對象
void Test2(){ HANDLE hFile = ::CreateFile(_T("aaa.txt"), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if(!hFile) { wcout<<L"CreateFile Failed ErroCode:"<<::GetLastError()<<endl; return ; } DWORD dwFileSize = ::GetFileSize(hFile,0); wcout<<L"FileSize:"<<dwFileSize<<endl; LARGE_INTEGER liDis = {0}; LARGE_INTEGER liRet = {0}; ::SetFilePointerEx(hFile,liDis,&liRet,FILE_END); wcout<<L"PreWrite File Pos:"<<liRet.LowPart<<endl; char * pFileContent = new char[10000000]; memset(pFileContent,‘z‘,10000000); DWORD dwReaded = 0; OVERLAPPED o_Write = {0}; o_Write.Offset = liRet.LowPart; o_Write.hEvent = ::CreateEvent(NULL,FALSE,FALSE,NULL); DWORD bReadDone = ::WriteFile(hFile, pFileContent, 10000000, &dwReaded, &o_Write); DWORD dwError = ::GetLastError(); if(!bReadDone && (dwError == ERROR_IO_PENDING)) { WaitForSingleObject(o_Write.hEvent,INFINITE); bReadDone = TRUE; } if(bReadDone) wcout<<L"I/O Code:"<<o_Write.Internal<<" TransedBytes:"<<o_Write.InternalHigh<<endl; else wcout<<"Error:"<<::GetLastError()<<endl; ::CloseHandle(hFile); delete [] pFileContent;}
- 可提醒IO
void Test3(){ //可提醒IO HANDLE hFile = ::CreateFile(_T("aaa.txt"), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if(!hFile) { wcout<<L"CreateFile Failed ErroCode:"<<::GetLastError()<<endl; return ; } DWORD dwFileSize = ::GetFileSize(hFile,0); wcout<<L"FileSize:"<<dwFileSize<<endl; LARGE_INTEGER liDis = {0}; LARGE_INTEGER liRet = {0}; ::SetFilePointerEx(hFile,liDis,&liRet,FILE_END); wcout<<L"PreWrite File Pos:"<<liRet.LowPart<<endl; char * pFileContent = new char[10000000]; memset(pFileContent,‘g‘,10000000); DWORD dwReaded = 0; OVERLAPPED o_Write = {0}; o_Write.Offset = liRet.LowPart; DWORD bReadDone = ::WriteFileEx(hFile, pFileContent, 10000000, &o_Write, FileIOCompletionRoutine); ::CloseHandle(hFile); SleepEx(10000,TRUE); delete [] pFileContent;}
可提醒IO的優劣:
(1)由於回呼函數的原因,最終不得不把大量資訊放在全域變數中。使代碼變的更加複雜
(2)發出請求線程和完成處理必須是同一線程,沒有達到線程負載平衡
可提醒IO相關函數
(1)QueueUserAPC函數
a.這個函數允許我們手動增加APC項。
b.可以強制線程退出等待狀態比如WaitForSingleObjectEx 以下是範例程式碼
VOID WINAPI APCFunc(ULONG_PTR pvParam){ //Nothing To Do}UINT WINAPI ThreadFunc(PVOID pvParam){ wcout<<L"start Wait...."<<endl; DWORD dw = ::WaitForSingleObjectEx(pvParam,INFINITE,TRUE); if(dw == WAIT_OBJECT_0) { wcout<<L"Event signaled"<<endl; return 0; } else if(dw == WAIT_IO_COMPLETION) { wcout<<L"QueueUserApc Forced us out of a wait state"<<endl; return 0; } return 0;}void Test4(){ //利用QueueUserApc來停止線程等待 HANDLE hEvent = ::CreateEvent(NULL,FALSE,FALSE,NULL); HANDLE hThread = (HANDLE) _beginthreadex(NULL,0,ThreadFunc,hEvent,0,NULL); Sleep(5000); QueueUserAPC(APCFunc,hThread,NULL); WaitForSingleObject(hThread,INFINITE); CloseHandle(hThread); CloseHandle(hEvent);}
- I/O完成連接埠
待續