2017-05-13 41 views
-1

我想Windows重疊IO,但我似乎無法讓它異步工作。我編譯並運行了下面的程序,但它從不打印任何內容,只是默默地完成。我讀過小讀取可能會同步,這就是爲什麼我故意選擇讀取512MB。窗口重疊IO實際上塊

const DWORD Size = 1<<29; // 512MB 
    char* Buffer = (char*)malloc(Size); 
    DWORD BytesRead; 
    OVERLAPPED Overlapped; 
    memset(&Overlapped, 0, sizeof(Overlapped)); 

    HANDLE File = CreateFile("BigFile", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL); 
    assert(File!=INVALID_HANDLE_VALUE); 

    DWORD Result = ReadFileEx(File, Buffer, Size, &Overlapped, NULL); // This line takes 150ms according to the debugger 
    assert(Result); 

    while(!GetOverlappedResult(File, &Overlapped, &BytesRead, FALSE)) { 
    printf("Waiting...\n"); 
    } 

至於更多的信息,我的ReadFileEx通話過程中加強代碼到調試器,以及Overlapped.InternalHigh值被更新(具有相同的價值Size)。

我試着VirtualAlloc更換mallocReadFileExReadFile,加入FILE_FLAG_NO_BUFFERING,並檢查的ReadFile的回報率爲0和GetLastErrorERROR_IO_PENDING讀之後。我試過使用RAMMap來查看文件是否在緩存中,但只有96KB。

我與8GB的內存運行Windows 10(版本1703)。

+0

也許該文件是由OS緩存,所以OS決定,它可以很容易地服務立即閱讀? – EOF

+0

@EOF會嚴重緩存整個512MB +文件嗎?另外,如果它被緩存了,我的讀取仍然需要150ms ......那麼如果它不能保證我快速返回,那麼重疊點有什麼意義呢? – Lutopia

+1

這實際上與緩存相關。開放文件'FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING'並分配'PVOID緩衝=的VirtualAlloc(0,大小,MEM_COMMIT,PAGE_READWRITE)'(必須對非緩存對齊讀取) - 檢查結果。和你的情況更好地使用'ReadFile'(不'Ex') - 返回給你假在這種情況下,與去年的錯誤 - 'ERROR_IO_PENDING' – RbMm

回答

-2

好,我懂了工作,一切都要歸功於@RbMm。

內存分配沒有改變,但FILE_FLAG_NO_BUFFERING標誌和使用ReadFile使它工作。我試圖ReadFileEx後使用SleepEx,它爲0,這證明@RbMm點的lpCompletionRoutine不可選的,但強制扔訪問衝突。 (對我來說,這意味着我將使用ReadFile,因爲我不想完成例程)

至於爲什麼花了我很長時間才意識到發生了什麼:我相信調試器太多了,顯然闖入調試器並沒有停止IO進程,這意味着內存仍在OVERLAPPED結構內更新,這讓我覺得事情是瞬間的。最重要的是,我期望ReadFile能夠快速返回,但如果我嘗試讀取512MB,實際上需要20ms,當我請求較小的金額時,速度會更快。

感謝大家對你的建議:)

爲了完整起見,這裏的工作程序:

const DWORD Size = 1<<20; 
    char* Buffer = (char*)malloc(Size); 
    DWORD BytesRead; 
    OVERLAPPED Overlapped; 
    memset(&Overlapped, 0, sizeof(Overlapped)); 

    HANDLE File = CreateFile("BigFile", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING|FILE_FLAG_OVERLAPPED, NULL); 
    assert(File!=INVALID_HANDLE_VALUE); 
    DWORD Result = ReadFile(File, Buffer, Size, NULL, &Overlapped); 
    assert(Result==FALSE && GetLastError()==ERROR_IO_PENDING); 
    while(!GetOverlappedResult(File, &Overlapped, &BytesRead, FALSE)) { 
    printf("Waiting...\n"); 
    } 
+1

和「ReadFileEx」 - 對最終結果和操作沒有不同時間,但我現在發現'lpCompletionRoutine'是強制參數,不是可選的。它總是必須指向正確的(可以清空)例程。否則如果在以* alertable *模式成功調用'ReadFileEx'後會發生崩潰。所以'ReadFileEx(File,Buffer,Size,&Overlapped,NULL);'是錯誤的。爲演示添加下一個代碼if(Result)SleepEx(INFINITE,TRUE);'結尾。在完成'GetOverlappedResult'之後 – RbMm