1. 程式人生 > >OVERLAPPED I/O 非同步APC

OVERLAPPED I/O 非同步APC

APC簡介:APC

第一個例子. 第二個例子使用APC 來解決一些問題

/*
   首先使用 OVERLAPPED  結構, 其中有Event 物件, 可用可不用,這個例子先不用

   CreateFile 其中一個引數使用 FILE_FLAG_OVERLAPPED 
    
   ReadFile  默認同步, 在最後一個引數使用 OVERLAPPED  ;
   ReadFile  返回TRUE ,則代表已經讀完了
             否則應該檢查 GetLastError , 系統是否為此安排了等待.

   如果 GetLastError == ERROR_IO_PENDING ,則成功了, 等著取資料, 否則失敗

   之後可以使用 GetOverlappedResult(最後一個引數為TRUE) / WaitForSingObject 來等待直到完成;
   
    
*/


void read_overlapped(const TCHAR * path)
{
    //這裡沒有使用其中的 Event 物件. 
    OVERLAPPED overlap = {0};
    DWORD bytesReaded = 0;
    BOOL ret = FALSE;
    char * buf = new char[8196 * 10];

    // 注意:FILE_FLAG_OVERLAPPED 

    HANDLE hFile = CreateFile(path,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);
    if(INVALID_HANDLE_VALUE == hFile){
        cout << "INVALID_HANDLE_VALUE" << endl;
        return;
     }

    //從哪開始讀檔案 
    overlap.Offset = 0;

    //注意overlap 需要傳入
    ret = ReadFile(hFile,buf,8196*10,&bytesReaded
                    ,&overlap);

    //直接就完成了, 您的計算機硬碟可真快
    if(ret){
        cout << "done :" <<  bytesReaded << endl;
        cout << buf << endl;
    }
    else
    {
        //檢測一下錯誤, 確認是否已經進入準備狀態
        DWORD err = GetLastError();

        //ok
        if(ERROR_IO_PENDING == err )
        {
            

            //GetOverlappedResult(hFile,&overlap,&bytesReaded,TRUE); 相當於WaitForSingObject
            //這樣其實不太好 , 浪費cpu.
            while(1){
                cout << "LOADing: " << GetLastError() << endl;
                 ret = GetOverlappedResult(hFile,&overlap,&bytesReaded,FALSE);
                 if(ret){
                     cout << "ret:" << ret << ",bytesread:" << bytesReaded << endl;
                     break;
                 }
            }
        }
        else
        {
            cout << "err : " << err << endl;
        }
    }
    CloseHandle(hFile);
}

通過OVERLAPPED 中的事件物件,對同一個檔案讀取多次 . 

void read_overlapped2(const TCHAR * path)
{
    HANDLE event_handles[2];
    OVERLAPPED overlap[2] = {0};
    char * buf[2] = {0};
    DWORD  num = 0;
    HANDLE hFile = CreateFile(path,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);
    if(INVALID_HANDLE_VALUE == hFile){
        cout << "INVALID_HANDLE_VALUE" << endl;
        return;
     }

    BOOL ret = 0;
    int success_len = 0;
    for(int i = 0; i < 2; ++i){
        event_handles[i] = CreateEvent(0,TRUE,FALSE,NULL);
        overlap[i].hEvent = event_handles[i];
        overlap[i].Offset = i*1000 + i;
        buf[i] = new char[8196 * 1024];
        ret = ReadFile(hFile,buf[i],8196 +overlap[i].Offset  ,&num,&overlap[i]);
        if(ret){
            cout << "index:" << i << ", is done" << endl;
            cout << "index:" << i << ",num:" << num;
            cout << "index:" << i << buf[i] << endl;
            ++success_len;
        }
        else {
            if(GetLastError() != ERROR_IO_PENDING){
                    cout << "index:" << i << "failed" << endl;
                    delete[] buf[i];
                    SetEvent(event_handles[i]);
            }
            else {
                ++success_len;
            }
        }
    }
    cout << "success_len:" << success_len << endl;
    WaitForMultipleObjects(success_len,event_handles,TRUE,-1);
    ret = GetOverlappedResult(hFile,&overlap[0],&num,FALSE);
    cout << "ret:" << ret << ", num:" << num << endl;
    ret = GetOverlappedResult(hFile,&overlap[1],&num,FALSE);
    cout << "ret:" << ret << ", num:" << num << endl;
    CloseHandle(hFile);

}

使用ReadFileEx APC:

const int count = 2;
HANDLE event_io;
void CALLBACK ioCompletionRoutine(
	_In_    DWORD        dwErrorCode,
	_In_    DWORD        dwNumberOfBytesTransfered,
	_Inout_ LPOVERLAPPED lpOverlapped
	)
{
	int index = (int)lpOverlapped->hEvent;
	printf("index : %d , readbytes: %d ,err:%d\n", index, dwNumberOfBytesTransfered, dwErrorCode);
	if (++index == count){
		SetEvent(event_io);
	}
}

void test_readfileex(const TCHAR * path)
{
	event_io = CreateEvent(0, TRUE, FALSE, 0);
	const int bufsize = 2 << 13;
	HANDLE hFile =CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
		FILE_FLAG_OVERLAPPED, NULL);
	if (INVALID_HANDLE_VALUE == hFile){
		printf("createfile failed");
		return;
	}

	OVERLAPPED overlap[count] = { 0 };
	TCHAR* buf[count] = { 0 };
	DWORD ret = 0 , err = 0;
	for (int i = 0; i <count; ++i){
		overlap[i].hEvent = (HANDLE)i;
		overlap[i].Offset = i *bufsize + i;
		buf[i] = new TCHAR[bufsize];
		ret = ReadFileEx(hFile, buf[i], bufsize, &overlap[i], ioCompletionRoutine);
		err = GetLastError();
		printf("ret:%d, err:%d\n", ret, err);
		if (!ret){
			// 出錯了 
		}
	}
	while (1){ 
		//注意是帶ex結尾的 . 這裡將阻塞ioCompletionRoutine 完成後將返回一次,所以需要判斷
		ret = WaitForSingleObjectEx(event_io, -1, TRUE);
		if (WAIT_OBJECT_0 == ret)
			break;
		else
			printf("WaitForSingleObjectEx return :%d\n", ret);
	}

	CloseHandle(hFile);
	CloseHandle(event_io);
	for (int i = 0; i < count; ++i)
		delete[] buf[i];
}