https://github.com/gongluck/Windows-Core-Program.gitc++
//第10章 同步設備IO與異步設備IO.cpp: 定義應用程序的入口點。 // #include "stdafx.h" #include "第10章 同步設備IO與異步設備IO.h" //可提醒IO回調 VOID WINAPI funComplete( _In_ DWORD dwErrorCode, _In_ DWORD dwNumberOfBytesTransfered, _Inout_ LPOVERLAPPED lpOverlapped ) { } //IO完成端口工做線程 DWORD WINAPI workthread(LPVOID lpThreadParameter) { DWORD NumberOfBytesTransferred; DWORD CompletionKey; OVERLAPPED* pOverlapped; BOOL bres = GetQueuedCompletionStatus(lpThreadParameter, &NumberOfBytesTransferred, &CompletionKey, &pOverlapped, INFINITE); //GetQueuedCompletionStatusEx可獲取多個IO請求結果 DWORD dres = GetLastError(); return 0; } int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { //打開(建立)文件 HANDLE hFile = CreateFile(TEXT("第10章 同步設備IO與異步設備IO.cpp"), GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr); if (hFile == INVALID_HANDLE_VALUE) { MessageBox(nullptr, TEXT("打開文件失敗!"), TEXT("error"), MB_OK); return 0; } //文件類型 DWORD dres = GetFileType(hFile); //dres == FILE_TYPE_DISK //文件大小 LARGE_INTEGER li; BOOL bres = GetFileSizeEx(hFile, &li);//邏輯大小 li.LowPart = GetCompressedFileSize(TEXT("第10章 同步設備IO與異步設備IO.cpp"), (DWORD*)&li.HighPart);//物理大小 //文件指針 li.QuadPart = 0; bres = SetFilePointerEx(hFile, li, nullptr, FILE_END); bres = SetFilePointerEx(hFile, li, &li, FILE_CURRENT); bres = SetEndOfFile(hFile); li.QuadPart = 0; bres = SetFilePointerEx(hFile, li, nullptr, FILE_BEGIN); //同步IO char* buf = new char[100]; bres = ReadFile(hFile, buf, 100, &dres, nullptr); delete []buf; buf = nullptr; //刷新緩衝區 bres = FlushFileBuffers(hFile); //CancelSynchronousIo //取消線程未完成的同步IO請求 //關閉文件 CloseHandle(hFile); hFile = nullptr; //異步IO HANDLE hFile2 = CreateFile(TEXT("第10章 同步設備IO與異步設備IO.cpp"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr); OVERLAPPED ol; ol.Offset = 1024; ol.OffsetHigh = 0; ol.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); char* buf2 = new char[1024]; bres = ReadFile(hFile2, buf2, 1024, nullptr, &ol);//異步方式老是返回FALSE dres = GetLastError(); switch (dres) { case ERROR_IO_PENDING: //IO請求添加成功 //WaitForSingleObject(hFile2, INFINITE); WaitForSingleObject(ol.hEvent, INFINITE); break; case ERROR_INVALID_USER_BUFFER: case ERROR_NOT_ENOUGH_MEMORY: break; case ERROR_NOT_ENOUGH_QUOTA: break; default: break; } //取消隊列中的IO請求 //bres = CancelIo(hFile2); bres = CancelIoEx(hFile2, &ol); //bres = CancelIoEx(hFile2, nullptr); //bres = CloseHandle(hFile2); if (ol.hEvent != nullptr) { CloseHandle(ol.hEvent); ol.hEvent = nullptr; } //可提醒IO OVERLAPPED ol2; ol2.Offset = 1024; ol2.OffsetHigh = 0; ol2.hEvent = nullptr; dres = ReadFileEx(hFile2, buf2, 1024, &ol2, funComplete);//回調函數在同一個線程空間 //置爲可提醒狀態 //APC隊列中只要有一個,線程就不會進入睡眠 dres = SleepEx(INFINITE, TRUE); //WaitForSingleObjectEx //WaitForMultipleObjectsEx //SignalObjectAndWait //GetQueuedCompletionStatusEx //MsgWaitForMultipleObjectsEx dres = GetLastError();//WAIT_IO_COMPLETION //手動添加一項到APC隊列 //可讓目標線程結束睡眠 dres = QueueUserAPC((PAPCFUNC)funComplete, GetCurrentThread(), NULL); //IO完成端口 HANDLE iocp = CreateIoCompletionPort(hFile2, nullptr, 1, 2); HANDLE hts[2]; for (int i = 0; i < 2; ++i) hts[i] = CreateThread(nullptr, 0, workthread, iocp, 0, nullptr); bres = PostQueuedCompletionStatus(iocp, 100, 1, &ol); //模擬發送IO請求完成 bres = ReadFile(hFile2, buf2, 1024, nullptr, &ol2); dres = GetLastError(); WaitForMultipleObjects(2, hts, TRUE, INFINITE); for (int i = 0; i < 2; ++i) { CloseHandle(hts[i]); hts[i] = nullptr; } CloseHandle(iocp); iocp = nullptr; CloseHandle(hFile2); hFile2 = nullptr; delete[]buf2; buf2 = nullptr; system("pause"); return 0; }