これは、最初から (Windows 3.x 以降) FindFirstChangeNotification() Win32 API の厄介な癖であり、FileSystemWatcher は単にその API をラップしているように見えます。タイマー アプローチ (上記) が一般的な回避策です。
私は通常、FileSystemWatcher をラップし、複数変更呼び出しのフィルタリングを行うクラスを作成します。書くには少し余分な作業が必要ですが、再利用することで成果が得られます。
public class FileChangeMonitor
{
private FileSystemWatcher _fsw;
DateTime _lastEventTime;
public event FileSystemEventHandler Changed;
public FileChangeMonitor(string path, string filter)
{
_fsw = new FileSystemWatcher(path, filter);
_fsw.Changed += new FileSystemEventHandler(_fsw_Changed);
_fsw.EnableRaisingEvents = true;
_fsw.NotifyFilter = NotifyFilters.LastWrite;
_fsw.IncludeSubdirectories = false;
}
private void _fsw_Changed(object sender, FileSystemEventArgs e)
{
// Fix the FindFirstChangeNotification() double-call bug
if (DateTime.Now.Subtract(_lastEventTime).TotalMilliseconds > 100)
{
_lastEventTime = DateTime.Now;
if (this.Changed != null)
this.Changed(sender, e); // Bubble the event
}
}
}
その後、FileSystemWatcher とほとんど同じように FileChangeMonitor を使用できます。
FileChangeMonitor fcm = new FileChangeMonitor(path, filter);
fsm.Changed += new FileSystemEventHandler(fsm_Changed);
...
もちろん、上記のコードは Changed イベントと NotifyFilters.LastWrite のみを処理しますが、おわかりいただけると思います。