2009-11-17 63 views
5

我正在通過同時調用ReadDirectoryChangesW來看一個目錄。當有新文件可用時,我嘗試使用CreateFileGENERIC_READFILE_SHARE_READ立即訪問它,但這會給我ERROR_SHARING_VIOLATION。將文件放入監視目錄的過程在我嘗試讀取文件時並未完成寫入。等待一個文件可用於與Win32一起閱讀

是否有任何方法可靠地等待文件可供閱讀?我可以將該方法放入下面的循環中,但我希望有更好的方法。

while ((hFile = CreateFile (path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) 
{ 
    if (GetLastError() == ERROR_SHARING_VIOLATION) 
     Sleep (500); 
    else 
     break; // some other error occurred 
} 

if (hFile == INVALID_HANDLE_VALUE) 
{ 
    // deal with other error 
    return 0; 
} 

ReadFile (...); 
+0

我認爲這是C++?如果它是C#,則可以使用BCL中的SystemFileWatcher對象。 – 2009-11-17 05:27:50

+0

Win32 == C API,我會重播。 – dreamlax 2009-11-17 05:31:35

回答

2

沒有關於我知道的封閉文件上的通知的用戶模式API。你提出的循環可能是最好的方法。你可以做的唯一的其他事情就是觀察過濾器驅動程序ala中的CloseFile進程監視程序,但是... ...

0

如果你知道如何創建文件,可能要等到文件停止增長爲X秒,或者等到一個哨兵文件被刪除。或者感知創建它們的程序的狀態。

+0

不幸的是,我不知道如何生成文件或將其放入監視文件夾中的過程(它可能是任何程序,或者可能是用戶拖放文件等)。 – dreamlax 2009-11-17 05:56:37

5

我不認爲有關於您正在尋找的事件的通知,但作爲改進,我會建議進行性延遲。這樣,如果用戶將文件在Excel中保持打開狀態一小時,您將獲得像拖放這樣的東西的快速響應時間,並且不會使CPU處於嚴密的循環狀態。

int delay= 10; 
while ((hFile = CreateFile (path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) 
{ 
    if (GetLastError() == ERROR_SHARING_VIOLATION) { 
     Sleep (delay); 
     if (delay<5120) // max delay approx 5.Sec 
      delay*= 2; 
    } 
    else 
     break; // some other error occurred 
} 
2

正如@馬特戴維斯說,不幸的是沒有用戶模式的API,但有是取決於你的用例(我已經寫在下面我的)一種解決方法,你想要什麼可以做的而已。

ZeroMemory(&overlapped, sizeof(OVERLAPPED)); 
overlapped.hEvent = hChangeEvent; 

// ...  
ReadDirectoryChangesW(hSpoolPath, 
         eventBuffer, 
         EVENT_BUF_LENGTH, 
         FALSE, 
         FILE_NOTIFY_CHANGE_LAST_WRITE, // <---- 
         NULL, 
         &overlapped, 
         NULL); 
// ... 
HANDLE events[2]; 

events[0] = hChangeEvent; 
events[1] = hCancelEvent; 

DWORD wRc = WaitForMultipleObjects(2, events, FALSE, DIRECTORY_WATCH_TIMEOUT); 

最後寫入時間得到儘快擁有的進程創建文件後關閉句柄更新:

什麼在過去的工作對我來說是調用ReadDirectoryChangesW時登記爲FILE_NOTIFY_CHANGE_FILE_NAMEFILE_NOTIFY_CHANGE_LAST_WRITE代替並寫信給它。

我的用例是一個通過TCP/IP接收到HTTP請求的進程,並將HTTP主體寫入一個目錄,其中一個進程在接收進程寫完後立即將其拾取(然後關閉處理它。 http-server是寫入該目錄的唯一進程,所以我可以依賴create-write-close模式。

+0

ReadDirectoryChangesW在註冊FILE_NOTIFY_CHANGE_LAST_WRITE時通知我兩次,然後將文件添加到該文件夾​​。你使用了哪個通知? – Will 2017-08-12 18:36:39