Waiting until a file is available for reading with Win32

后端 未结 4 597
情话喂你
情话喂你 2020-12-07 01:22

I\'m watching a directory by calling ReadDirectoryChangesW synchronously. When a new file is available, I try to access it immediately with CreateFile

相关标签:
4条回答
  • 2020-12-07 01:52

    There's no user-mode API for notifications on a closed file that I'm aware of. The loop you've proposed is really probably the best way. The only other thing you could do would be to watch for CloseFile in a filter driver ala Process Monitor, but yuck...

    0 讨论(0)
  • 2020-12-07 01:53

    As @Matt Davis said, there is unfortunately no user-mode API but there is a workaround that depending on your use-case (I've written mine below) may do just what you want.

    What worked for me in the past was registering for FILE_NOTIFY_CHANGE_LAST_WRITE instead of FILE_NOTIFY_CHANGE_FILE_NAME when calling ReadDirectoryChangesW:

    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);
    

    The last write time gets updated as soon as the owning process closes the handle after creating the file and writing to it.

    My use-case was one process that received HTTP-requests via TCP/IP and wrote the HTTP-body into a directory, where another process picked it up as soon as the receiving process was finished writing (and consequently closing the handle) it. The http-server was the only process that wrote to that directory, so I could rely on the create-write-close pattern.

    0 讨论(0)
  • 2020-12-07 02:07

    I don't think there is a notification for the kind of event you're looking for, but as an improvement, I'd suggest progressive delays. This way you will get fast response times for stuff like a drag/drop and won't hog the CPU with a tight loop if the user keeps the file open for an hour in Excel.

    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
    }
    
    0 讨论(0)
  • 2020-12-07 02:07

    If you know something about how the file is created, maybe wait until the file stops growing for X seconds, or wait until a sentinel file is deleted. Or sense the state of the program which creates them.

    0 讨论(0)
提交回复
热议问题