Github
https://github.com/gongluck/Windows-Core-Program.git
//第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;
}