2012-03-05 3 views
4

ファイルがディスク上で更新されたときに通知を取得しようとしています。私はフラッシュが発生するとすぐにこの通知を得ることに興味がありますが、FileSystemWatcherはストリームが開いたり閉じたりしたときだけイベントを送信するようです。FileSystemWatcher変更イベント(LastWriteの場合)が信頼できない

以下のコードでは、ファイルに書き込みを行い、繰り返しバッファをディスクにフラッシュします。しかし、FileSystemWatcherは書き込みの開始時と終了時に一度だけ通知していました。

これらの通知を受け取る別の方法はありますか?それともポーリングを使うべきですか?

コード:

class Program 
{ 
    static void Main(string[] args) 
    { 
     FileSystemWatcher watcher = new FileSystemWatcher(Environment.CurrentDirectory, "Test.txt"); 
     watcher.Changed += watcher_Changed; 
     watcher.EnableRaisingEvents = true; 

     using(TextWriter writer = new StreamWriter("Test.txt")) 
     { 
      WriteData(writer); 
      WriteData(writer); 
      WriteData(writer); 
      WriteData(writer); 
     } 

     Thread.Sleep(10000); 
    } 

    private static void WriteData(TextWriter writer) 
    { 
     writer.WriteLine("Hello!"); 
     writer.Flush(); 
     Console.WriteLine(DateTime.Now.ToString("T") + "] Wrote data"); 
     Thread.Sleep(3000); 
    } 

    static void watcher_Changed(object sender, FileSystemEventArgs e) 
    { 
     Console.WriteLine(DateTime.Now.ToString("T") + "] Watcher changed!"); 
    } 
} 

UPDATE 1

私は秒を表示するためのDateTimeのToString関数を修正しました。上のコードの出力は次のとおりです。

11:37:47 AM] Watcher changed! 
11:37:47 AM] Wrote data 
11:37:50 AM] Wrote data 
11:37:53 AM] Wrote data 
11:37:56 AM] Wrote data 
11:37:59 AM] Watcher changed! 

ありがとう!

+2

'FileSystemWatcher'が信頼できないの適用を前提と多くの理由から。すべての更新の信頼できる通知が必要な場合は、両側を変更し、それらの間に他の明示的な通信チャネルを使用します。 –

+0

私は同意すると良い選択になるかもしれませんが、私の場合は不可能です。 – VitalyB

+0

ああ、私はあなたのサンプルコード/記述から、この統合問題の両側のコードを管理していると仮定しました。そうでない場合は、私が何を推薦するか分からない。私は思うだろう。 –

答えて

1

これはFileSystemWatcherとは関係ありません。ウォッチャーは、ファイルシステムのLastWrite属性の更新に反応します。

など。 NTFSはすべての書き込みでLastWriteを更新しません。この値はキャッシュされ、ストリームがクローズされたとき、またはその他の特定されていない時間にのみ書き込まれます。 This documentと表示されます

タイムスタンプはさまざまな理由でさまざまな理由で更新されます。ファイルのタイムスタンプに関する唯一の保証は、変更を行うハンドルが閉じられたときにファイルの時刻が正しく反映されることです。 [...] NTFSファイルシステムは、最大で1時間によって、ファイルの最終アクセス時刻の更新を遅らせる最後のアクセス

後、私は同様のキャッシュが書き込みのため

+0

興味深い!それは本当です、それは非常に理由かもしれません。 – VitalyB

2

ここで問題の一つは、イベントがそのCPU時間のスライスを取得する前にすべての書き込みが実行されるということです。 MSDN states

Changedイベントは、変更がサイズに作られている場合、システムは、最終書き込み時刻、最終アクセス時刻、または監視されているディレクトリ内のファイルまたはディレクトリのセキュリティ権限を属性上げています。私がテストを行なったし、私が得たものWRITEDATA(...)、の各呼び出しの後に眠るを挿入

9時32

た]ウォッチャー変更します!

09:32]ウォッチャーが変更されました。

09:32] -----> -----> ----->

データを書き込んだ]

09:32データを書き込んだ]

09:32データを書き込みました

09:32] ----->データを書きました

09:32]ウォッチャーが変更されました!

09:32]ウォッチャーが変更されました。

私は、Flush()を呼び出した直後にevenが起動されることを証明していると思います。イベントハンドラがいつ実行されるのかという問題です。 あなたのプロジェクトの具体的なニーズはわかりませんが、私は投票しません。 FileSystemWatcherは私の意見でやりたいことをやっているので、無駄に思える。

編集:私がこれを投稿したときに私の脳はまだ考えていないと思う。 ストリームを開いたり閉じたりしたときに発生するという結論は、より論理的で正しいと思われます。 私は、あなたがフラッシュして呼び出すと、何とかそれを見つけたときに、それが発火する「証明」を探していたと思います。

更新 は、私はちょうどUSNジャーナルで突くを持っていたし、文句を言わない何をしたいあなたを得るようですどちらかそれはファイルが閉じられるだけレコードを書き込みとして。 - >http://msdn.microsoft.com/en-us/library/aa363803(VS.85).aspx また、USN-Viewer in C#http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/c1550294-d121-4511-ac32-31551497f64eも読んで興味深いかもしれません。

また、DiskMonを実行して、リアルタイムで変更が反映されているかどうかを確認しました。それはありませんが、それが意図的であるかどうかはわかりません。しかし、両方の問題は、管理者権限を必要とすることです。 あなたはFileSystemWatcherに悩まされていると思います。 (とにかくアップデートが必要なのは、別のプログラムが開いている/ロックしている間にファイルを読むことができないからです)

ps:私は気づいたばかりのBugAidの開発者それは最近のことです - それはすごく見えます:)

+0

お返事ありがとうございます。私のコードでは、各書き込みとフラッシュの後にすでにスリープ(3000)があるので、FileSystemWatcherはイベントを送信する際に問題を起こすべきではありません。また、あなたが投稿した出力から、ストリームが閉じられるまで、実際にFSWがイベントを送受信していないようです...私は、コードをDateTimeのToStringを修正しました。あなたがBugAidを好きでうれしい:)それについて何か質問があればお知らせください! – VitalyB

+0

ああ、私がそれを見落としたばかげた感じ、あなたが起きた後にコードを最初に読んでみることは、そのような良い考えではないと思う。編集:大丈夫、私は今あなたが意味するものを参照してください。 – Brunner

関連する問題