9

ReadDirectoryChangesW同期的に呼び出してディレクトリを監視しています。新しいファイルが利用可能になると、 と を使用CreateFileしてすぐにアクセスしようとしますが、これにより. 監視対象のディレクトリにファイルを配置するプロセスは、ファイルを読み取ろうとするまでに書き込みを終了しません。GENERIC_READFILE_SHARE_READERROR_SHARING_VIOLATION

ファイルが読み取り可能になるまで確実に待機する方法はありますか? メソッドを以下のようなループに入れることができますが、もっと良い方法があることを願っています。

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 (...);
4

4 に答える 4

8

あなたが探している種類のイベントの通知はないと思いますが、改善として、漸進的な遅延をお勧めします. このようにして、ドラッグ アンド ドロップなどの応答時間を短縮し、ユーザーが Excel で 1 時間ファイルを開いたままにしておくと、タイトなループで 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
}
于 2009-11-17T18:55:40.853 に答える
2

@Matt Davisが言ったように、残念ながらユーザーモードAPIはありませんが、ユースケースに応じて(私は以下に書いています)、あなたが望むことをするかもしれない回避策があります.

過去に私にとってうまくいったのは、呼び出すときではFILE_NOTIFY_CHANGE_LAST_WRITE なく 登録することでした:FILE_NOTIFY_CHANGE_FILE_NAMEReadDirectoryChangesW

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

ファイルを作成して書き込みを行った後、所有プロセスがハンドルを閉じるとすぐに、最終書き込み時刻が更新されます。

私のユースケースは、TCP/IP 経由で HTTP リクエストを受信し、HTTP 本体をディレクトリに書き込んだ 1 つのプロセスでした。このディレクトリでは、受信プロセスが書き込みを完了するとすぐに別のプロセスがそれを取得しました (その結果、ハンドルが閉じられました)。そのディレクトリに書き込みを行うプロセスは http-server だけだったので、create-write-close パターンに頼ることができました。

于 2014-10-13T06:52:58.967 に答える
2

私が知っている閉じたファイルに関する通知用のユーザーモード API はありません。あなたが提案したループは、おそらく最良の方法です。あなたができる唯一の他のことはCloseFile、プロセスモニターのフィルタードライバーで監視することですが、うん...

于 2009-11-17T05:39:23.627 に答える
0

ファイルの作成方法について何か知っている場合は、ファイルの成長が X 秒間停止するまで待つか、センチネル ファイルが削除されるまで待ちます。または、それらを作成するプログラムの状態を感知します。

于 2009-11-17T05:41:36.383 に答える