見過網上好多的完成連接埠和網路通訊的文章,呵呵,這裡就簡單的說說檔案非同步IO和完成連接埠,這裡僅僅說說讀取操作。下面是一些總結,很少有人提及,認真的看過MSDN文檔之後得出的,歡迎指正。
- 要對檔案非同步IO操作,需要在檔案建立的時候指定FILE_FLAG_OVERLAPPED屬性的;
- 非同步ReadFileEx是不能讀取和IO完成連接埠綁定的檔案控制代碼的;
- 非同步ReadFileEx對OVERLAPPED的hEvent忽視;
- 非同步完成後可以出發回調,回調介面需要指定WINAPI屬性,實際上就是_stdcall,如果不指定則預設是_cdecl屬性,回調完成後,會崩潰的;
- 最後需要等待。
這裡簡單的附上一段非同步代碼:
#include <process.h>#include <Windows.h>VOID WINAPI rt( __in DWORD dwErrorCode, __in DWORD dwNumberOfBytesTransfered, __inout LPOVERLAPPED lpOverlapped){ printf("rt call back\n");}int _tmain(int argc, _TCHAR* argv[]){ OVERLAPPED *ol = new OVERLAPPED; memset(ol, 0, sizeof *ol); HANDLE file = CreateFile("ReadMe.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED , NULL); if(file == INVALID_HANDLE_VALUE) { goto mem_free1; } size_t buf_len = 1024; char *buf = new char[buf_len]; if(!buf) { goto mem_free1; } if(!ReadFileEx(file, buf, buf_len, ol, rt)) { goto mem_free; } SleepEx(INFINITE, TRUE);mem_free: delete []buf;mem_free1: delete ol; CloseHandle(file);return 0;}
對於ReadFile,主線程在觸發非同步作業之後,就需要有另外的線程來做輔助工作,可以使用event事件,這裡主要介紹完成連接埠,沒有多少好說的,也貼上代碼吧:
#include <process.h>#include <windows.h>//建立一個IO完成連接埠HANDLE CreateNewCompletionPort(DWORD dwNumberOfConcurrentThreads){ return( CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, dwNumberOfConcurrentThreads));}//將裝置與完成連接埠管理起來BOOL AssociateDeviceWithCompletionPort(HANDLE hCompletionPort, HANDLE hDevice, DWORD dwCompletionKey) { HANDLE h = CreateIoCompletionPort(hDevice, hCompletionPort, dwCompletionKey, 0); return (h == hCompletionPort);}void reader(void *in){ HANDLE port = (HANDLE)in; DWORD rcv_len = 0; ULONG_PTR my_key = 0; OVERLAPPED *ol1 = NULL; while(1) { if(!GetQueuedCompletionStatus(port, &rcv_len, &my_key, &ol1, INFINITE)) { int err = GetLastError(); continue; } else { _endthread(); } }}int _tmain(int argc, _TCHAR* argv[]){ int key = 12345; HANDLE port = CreateNewCompletionPort(4); if(!port) { int err = GetLastError(); return 0; } HANDLE file = CreateFile("ReadMe.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED , NULL); if(file == INVALID_HANDLE_VALUE) { CloseHandle(port); } OVERLAPPED *ol = new OVERLAPPED; memset(ol, 0, sizeof *ol); if(!AssociateDeviceWithCompletionPort(port, file, key)) { int err = GetLastError(); CloseHandle(port); CloseHandle(file); delete ol; return 0; } int buf_len = 1000; char *buf = new char[buf_len]; if(!buf) { CloseHandle(port); CloseHandle(file); delete ol; return 0; } HANDLE h_thread = (HANDLE)_beginthread(reader, 0, port); if(!ReadFile(file, buf, buf_len, NULL, ol)) { int err = GetLastError(); if(err != ERROR_IO_PENDING) { CloseHandle(port); CloseHandle(file); delete ol; WaitForSingleObject(h_thread, INFINITE); return 0; } } WaitForSingleObject(h_thread, INFINITE); CloseHandle(port); CloseHandle(file); delete ol; delete []buf; return 0;}