7

C#では、FileSystemWatcherオブジェクトを使用して特定のファイルを監視し、ファイルの作成、変更などの際にイベントを発生させることができます。

このクラスで私が抱えている問題は、ファイルを作成したプロセスがまだ書き込み中であっても、ファイルが作成された瞬間にイベントが発生することです。これは非常に問題があることがわかりました。特に、XMLドキュメントのようなものを読み込もうとしている場合、ファイルには、書き込みが完了するまで存在しない構造が必要です。

.NET(できれば2.0)には、ファイルがアクセス可能になった後にイベントを発生させる方法がありますか、それとも、ファイルが使用可能であることを確認するために例外がスローされなくなるまで、ファイルの読み取りを常に試行する必要がありますか?

4

4 に答える 4

5

ファイル システム ウォッチャーを使用して、ファイルがいつ変更されたかを確認できます。以前にファイルを閉じていたプログラムがファイルを閉じた後にのみ、「変更」されます。あなたが C# を要求したことは知っていますが、私の VB.Net ははるかに優れています。あなたまたは他の誰かが翻訳できることを願っています。

ファイルを開こうとし、利用できない場合はウォッチャーを追加し、ファイルが変更されるのを待ちます。ファイルが変更された後、再度開こうとします。ファイルが解放されない状況に陥る可能性があるため、120 秒以上待機すると例外がスローされます。また、実際のファイル ウォッチャーが作成される前にファイルが閉じられた可能性が小さい場合に備えて、5 秒のファイル変更を待機するタイムアウトを追加することにしました。

 Public Sub WriteToFile(ByVal FilePath As String, ByVal FileName As String, ByVal Data() As Byte)
        Dim FileOpen As Boolean
        Dim File As System.IO.FileStream = Nothing
        Dim StartTime As DateTime
        Dim MaxWaitSeconds As Integer = 120

        StartTime = DateTime.Now

        FileOpen = False

        Do
            Try
                File = New System.IO.FileStream(FilePath & FileName, IO.FileMode.Append)
                FileOpen = True

            Catch ex As Exception

                If DateTime.Now.Subtract(StartTime).TotalSeconds > MaxWaitSeconds Then
                    Throw New Exception("Waited more than " & MaxWaitSeconds & " To Open File.")
                Else
                    Dim FileWatch As System.IO.FileSystemWatcher

                    FileWatch = New System.IO.FileSystemWatcher(FilePath, FileName)
                    FileWatch.WaitForChanged(IO.WatcherChangeTypes.Changed,5000)
                End If

                FileOpen = False

            End Try

        Loop While Not FileOpen

        If FileOpen Then
            File.Write(Data, 0, Data.Length)
            File.Close()
        End If
    End Sub
于 2008-08-23T17:38:59.397 に答える
0

キベの答えは正しいようですが、私にはうまくいきませんでした。FileSystemWatcherにバグがあるようです。だから私は自分のWaitForChangedを書きました:

using (var watcher = new FileSystemWatcher(MatlabPath, fileName))
{
    var wait = new EventWaitHandle(false, EventResetMode.AutoReset);
    watcher.EnableRaisingEvents = true;
    watcher.Changed += delegate(object sender, FileSystemEventArgs e)
    {
       wait.Set();
    };
    if (!wait.WaitOne(MillissecondsTimeout))
    {
        throw new TimeoutException();
    }
 }
于 2009-07-12T01:33:20.683 に答える
0

標準クラスで実際にイベントが発生する方法があるかどうかはわかりませんが、最近行っていたいくつかの作業で同様の問題が発生しやすくなっています。

つまり、その時点でロックされていたファイルに書き込もうとしていました。結局、writeメソッドをラップして、数ミリ秒後に自動的に書き込みを再試行するようにしました。

大声で考えて、読み取り専用ステータスについてファイルをプローブできますか?保留中のファイル操作などのデリゲートをスタックできるファイルIOのラッパーを用意する価値があるかもしれません。

于 2008-08-23T15:59:13.660 に答える
0

OPEN_EXISTINGフラグとFILE_ALL_ACCESSを使用してループでCreateFileを使用します(またはサブセットのみが必要な場合は、http://msdn.microsoft.com/en-us/library/aa364399(VS.85).aspxを参照してください

-1(INVALID_ HANDLE_ VALUE)に対して返されたハンドルに失敗がないか調べます。まだポーリング中ですが、これにより例外スローのコストを節約できます。

編集:このエディター/マークアップはアンダースコアを処理できません!ああ!

于 2008-08-23T16:16:49.110 に答える