异步IO

異步IO是計算機作業系統對輸入輸出的一種處理方式：發起IO請求的執行緒不等IO操作完成，就繼續執行隨後的代碼，IO結果用其他方式通知發起IO請求的程序。與異步IO相對的是更為常見的「同步（阻塞）IO」：發起IO請求的執行緒不從正在調用的IO操作函數返回（即被阻塞），直至IO操作完成。

Windows作業系統的異步IO

Windows提供多種異步IO（也稱重疊IO）方式：

設備內核對象

IO設備在作業系統內核中表示為內核對象，因此具有可等待（waitable）內核對象狀態。例如：文件句柄，執行緒句柄等等。對於文件內核對象，當一個異步IO完成後，該文件句柄被置為觸發態。使用這種方式獲取異步IO完成的通知，缺點是如果在一個文件內核對象上同時有多個異步IO操作，只通過文件句柄的觸發無法辨識哪個異步IO操作完成了。
例子：
HANDLE hFile = CreateFileW(L"d:\\a.txt", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, 0); //设置异步IO的标志FILE_FLAG_OVERLAPPEDchar buffer[10] = {"abcd"};OVERLAPPED ol = { 0 };//用0初始化OVERLAPPED的结构ol.Offset = 2;/从文件的第三个字节开始IOBOOL rt = WriteFile(hFile, buffer, 5, NULL, &ol);//发起一个异步写操作//SetFileCompletionNotificationModes(hFile, FILE_SKIP_SET_EVENT_ON_HANDLE);//如此设置则文件内核对象就不会被触发if (rt == FALSE && GetLastError() == ERROR_IO_PENDING)//检查异步IO是否完成 {
WaitForSingleObject(hFile, INFINITE);//等待设备内核对象（文件）被触发。}CloseHandle(hFile);

GetOverlappedResult函數

也可以使用Windows API函數GetOverlappedResult直接阻塞/非阻塞等待指定的異步IO操作是否完成。該函數檢查OVERLAPPED結構中的Internal成員的值是否為STATUS_PENDING來判斷異步IO是否完成。

異步IO操作的完成通知用事件內核對象

在異步IO操作的read/write函數調用中給出的OVERLAPPED類型的參數中，可以指定一個內核事件對象。這個異步IO操作完成時，這個內核事件對象會被觸發。從而，等待在這個事件對象上的程序就會知道這個異步IO操作完成。
例子：
HANDLE hFile = CreateFileW(L"d:\\a.txt", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, 0); //设置异步IO的标志FILE_FLAG_OVERLAPPEDchar buffer[10] = {"abcd"};OVERLAPPED ol = { 0 };//用0初始化OVERLAPPED的结构ol.Offset = 2;/从文件的第三个字节开始IOHANDLE hEvent = CreateEvent(0, FALSE, FALSE, NULL);  
ol.hEvent = hEvent;//传递一个事件对象。  BOOL rt = WriteFile(hFile, buffer, 5, NULL, &ol);//发起一个异步写操作 if (rt == FALSE && GetLastError() == ERROR_IO_PENDING)//检查异步IO是否完成 {
WaitForSingleObject(ol.hEvent, INFINITE);//等待设备内核对象（文件）被触发。}CloseHandle(hEvent); 
CloseHandle(hFile);

可喚醒I/O

異步可喚醒I/O操作通過ReadFileEx/WriteFileEx函數指出完成過程回調函數。回調函數在該執行緒的可喚醒等待（alertable wait）中被執行。

完成埠

使用CreateIoCompletionPort函數創建一個完成埠。然後把文件句柄綁定到這個完成埠（通過CreateIoCompletionPort函數)。這個文件句柄上的異步IO操作完成時，會自動向這個完成完成埠發通知。執行緒通過GetQueuedCompletionStatus函數等待這個完成埠上的完成通知，然後從GetQueuedCompletionStatus的調用返回處恢復執行緒執行。

執行緒池I/O完成對象

使用CreateThreadpoolIo函數創建一個I/O完成對象，綁定了要執行異步I/O操作的文件句柄與待執行的回調函數。通過StartThreadpoolIo函數開始I/O完成對象的工作。每當綁定的文件句柄上的異步I/O操作完成，自動調用執行緒池上的執行緒執行指定的回調函數。
例子：
VOID CALLBACK OverlappedCompletionRoutine(PTP_CALLBACK_INSTANCE pInstance,  
                                          PVOID pvContext,  
                                          PVOID pOverlapped,  
                                          ULONG IoResult,  
                                          ULONG_PTR NumberOfBytesTransferred,  
                                          PTP_IO pIo)  
{  
    printf("OverlappedCompletionRoutine, transferred: %d bytes\n", NumberOfBytesTransferred);  
}  

HANDLE hFile = CreateFileW(L"d:\\a.txt", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, 0); //设置异步IO的标志FILE_FLAG_OVERLAPPEDPTP_IO pio = CreateThreadpoolIo(hFile, OverlappedCompletionRoutine, NULL, NULL);//将设备对象和线程池的IO完成端口关联起来。  StartThreadpoolIo(pio);char buffer[10] = {"abcd"};OVERLAPPED ol = { 0 };//用0初始化OVERLAPPED的结构ol.Offset = 2;/从文件的第三个字节开始IO   

BOOL rt = WriteFile(hFile, buffer, 5, NULL, &ol);//发起一个异步写操作 if(rt==FALSE && GetLastError()==ERROR_IO_PENDING)){  
   ::Sleep(4000); 
   //do somethings... }else{
   CancelThreadpoolIo(pio); 
}WaitForThreadpoolIoCallbacks(pio,false);CloseHandle(hFile); 
CloseThreadpoolIo(pio);//关闭线程池io完成对象