[C#] FileSystemWatcherで複数フォルダを監視する方法
C#でFileSystemWatcherを使用して複数のフォルダを監視するには、各フォルダに対して個別のFileSystemWatcherインスタンスを作成する必要があります。
各インスタンスに対して監視するディレクトリパスを設定し、変更イベント(例:Changed, Created, Deleted, Renamed)をハンドルするイベントハンドラを登録します。
これにより、指定した複数のフォルダ内でのファイルやディレクトリの変更を個別に監視し、適切な処理を行うことができます。
各FileSystemWatcherは独立して動作するため、必要に応じて異なる設定やフィルタを適用することも可能です。
複数フォルダの監視方法
複数のFileSystemWatcherインスタンスの作成
C#のFileSystemWatcherクラス
を使用すると、特定のフォルダ内のファイルシステムの変更を監視できます。
複数のフォルダを監視するには、それぞれのフォルダに対してFileSystemWatcher
のインスタンスを作成する必要があります。
以下は、複数のインスタンスを作成するサンプルコードです。
using System;
using System.IO;
using System.Windows.Forms;
public partial class MyForm : Form
{
private FileSystemWatcher watcher1;
private FileSystemWatcher watcher2;
public MyForm()
{
InitializeComponent();
CreateWatchers();
}
private void CreateWatchers()
{
// フォルダ1の監視
watcher1 = new FileSystemWatcher();
watcher1.Path = @"C:\Path\To\Folder1"; // 監視するフォルダのパス
watcher1.EnableRaisingEvents = true; // イベントを有効にする
// フォルダ2の監視
watcher2 = new FileSystemWatcher();
watcher2.Path = @"C:\Path\To\Folder2"; // 監視するフォルダのパス
watcher2.EnableRaisingEvents = true; // イベントを有効にする
}
}
このコードでは、FileSystemWatcher
のインスタンスを2つ作成し、それぞれ異なるフォルダを監視しています。
EnableRaisingEvents
プロパティをtrue
に設定することで、監視を開始します。
各インスタンスの設定と管理
各FileSystemWatcher
インスタンスには、監視するイベントを設定することができます。
例えば、ファイルの作成、変更、削除などのイベントを監視することが可能です。
以下のサンプルコードでは、イベントを設定し、イベントハンドラを追加しています。
private void CreateWatchers()
{
// フォルダ1の監視
watcher1 = new FileSystemWatcher();
watcher1.Path = @"C:\Path\To\Folder1";
watcher1.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite; // 監視する変更の種類
watcher1.Filter = "*.txt"; // 監視するファイルの種類
watcher1.Created += OnChanged; // 作成イベントのハンドラを追加
watcher1.Changed += OnChanged; // 変更イベントのハンドラを追加
watcher1.Deleted += OnChanged; // 削除イベントのハンドラを追加
watcher1.EnableRaisingEvents = true;
// フォルダ2の監視
watcher2 = new FileSystemWatcher();
watcher2.Path = @"C:\Path\To\Folder2";
watcher2.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite;
watcher2.Filter = "*.txt";
watcher2.Created += OnChanged;
watcher2.Changed += OnChanged;
watcher2.Deleted += OnChanged;
watcher2.EnableRaisingEvents = true;
}
private void OnChanged(object sender, FileSystemEventArgs e)
{
// 変更があった場合の処理
MessageBox.Show($"ファイルが変更されました: {e.FullPath}");
}
このコードでは、NotifyFilter
プロパティを使用して監視する変更の種類を指定し、Filter
プロパティで監視するファイルの種類を設定しています。
OnChangedメソッド
は、ファイルが変更されたときに呼び出されるイベントハンドラです。
イベントハンドラの共通化
複数のFileSystemWatcher
インスタンスで同じイベントハンドラを使用することで、コードの重複を避けることができます。
上記の例では、OnChangedメソッド
を共通のイベントハンドラとして使用しています。
これにより、各インスタンスで発生したイベントを一元的に処理できます。
このように、FileSystemWatcher
を使用することで、複数のフォルダを効率的に監視し、変更があった場合に適切な処理を行うことができます。
実装のベストプラクティス
リソース管理とパフォーマンス
FileSystemWatcher
を使用する際は、リソース管理が重要です。
特に、監視するフォルダが多い場合や、頻繁に変更が発生するフォルダを監視する場合、パフォーマンスに影響を与える可能性があります。
以下のポイントに注意して実装を行いましょう。
- インスタンスの適切な管理: 使用が終わった
FileSystemWatcher
インスタンスは、Disposeメソッド
を呼び出してリソースを解放します。 - イベントの無効化: 監視を一時的に停止する場合は、
EnableRaisingEvents
プロパティをfalse
に設定します。 - バッファサイズの調整:
InternalBufferSize
プロパティを設定することで、イベントのバッファサイズを調整できます。
大きな変更が頻繁に発生する場合は、バッファサイズを増やすことを検討します。
以下は、リソース管理のサンプルコードです。
private void DisposeWatchers()
{
if (watcher1 != null)
{
watcher1.EnableRaisingEvents = false; // イベントを無効化
watcher1.Dispose(); // リソースを解放
}
if (watcher2 != null)
{
watcher2.EnableRaisingEvents = false; // イベントを無効化
watcher2.Dispose(); // リソースを解放
}
}
エラーハンドリング
FileSystemWatcher
を使用する際には、エラーハンドリングも重要です。
ファイルシステムの変更に伴うエラーや、アクセス権限の問題などが発生する可能性があります。
以下の方法でエラーハンドリングを行いましょう。
- 例外処理:
try-catch
ブロックを使用して、エラーが発生した場合に適切に処理します。 - イベントの監視:
Error
イベントを使用して、FileSystemWatcher
がエラーを検出した際に通知を受け取ります。
以下は、エラーハンドリングのサンプルコードです。
private void OnChanged(object sender, FileSystemEventArgs e)
{
try
{
// 変更があった場合の処理
MessageBox.Show($"ファイルが変更されました: {e.FullPath}");
}
catch (Exception ex)
{
// エラーが発生した場合の処理
MessageBox.Show($"エラーが発生しました: {ex.Message}");
}
}
private void OnError(object sender, ErrorEventArgs e)
{
// エラーが発生した場合の処理
MessageBox.Show($"エラーが発生しました: {e.GetException().Message}");
}
スレッドセーフな実装
FileSystemWatcher
は、イベントが発生するスレッドとUIスレッドが異なる場合があります。
そのため、スレッドセーフな実装が必要です。
以下のポイントに注意して実装を行いましょう。
- Invokeメソッドの使用: UIスレッドでの操作が必要な場合は、
Invokeメソッド
を使用してUIスレッドに処理を委譲します。 - ロックの使用: 複数のスレッドから同時にアクセスされる可能性があるデータに対しては、
lock
文を使用して排他制御を行います。
以下は、スレッドセーフな実装のサンプルコードです。
private void OnChanged(object sender, FileSystemEventArgs e)
{
if (InvokeRequired)
{
// UIスレッドでの処理を要求
Invoke(new Action(() => OnChanged(sender, e)));
return;
}
// 変更があった場合の処理
MessageBox.Show($"ファイルが変更されました: {e.FullPath}");
}
このように、リソース管理、エラーハンドリング、スレッドセーフな実装に注意を払うことで、FileSystemWatcher
を効果的に活用し、安定したアプリケーションを構築することができます。
応用例
特定のファイルタイプのみを監視する
FileSystemWatcher
を使用して特定のファイルタイプのみを監視することができます。
これにより、不要なイベントをフィルタリングし、必要な変更のみを処理することが可能です。
Filter
プロパティを使用して、監視するファイルの拡張子を指定します。
以下は、.txt
ファイルのみを監視するサンプルコードです。
private void CreateWatchers()
{
watcher1 = new FileSystemWatcher();
watcher1.Path = @"C:\Path\To\Folder";
watcher1.Filter = "*.txt"; // .txtファイルのみを監視
watcher1.EnableRaisingEvents = true;
}
この設定により、指定したフォルダ内の.txt
ファイルに対する変更のみが監視され、他のファイルタイプの変更は無視されます。
ネットワークドライブの監視
ネットワークドライブを監視する場合も、FileSystemWatcher
を使用することができます。
ネットワークドライブのパスを指定することで、リモートのフォルダ内の変更を監視できます。
ただし、ネットワークの遅延や接続の問題に注意が必要です。
以下は、ネットワークドライブを監視するサンプルコードです。
private void CreateWatchers()
{
watcher1 = new FileSystemWatcher();
watcher1.Path = @"\\NetworkDrive\SharedFolder"; // ネットワークドライブのパス
watcher1.EnableRaisingEvents = true;
}
このコードでは、ネットワークドライブ上のSharedFolder
を監視しています。
ネットワークの状態に応じて、エラーハンドリングを行うことが重要です。
大量のフォルダを効率的に監視する
大量のフォルダを監視する場合、各フォルダに対して個別にFileSystemWatcher
を作成するのは非効率です。
配列やリストを使用して、動的にFileSystemWatcher
のインスタンスを生成する方法が効果的です。
以下は、複数のフォルダを効率的に監視するサンプルコードです。
private List<FileSystemWatcher> watchers = new List<FileSystemWatcher>();
private string[] foldersToWatch = { @"C:\Path\To\Folder1", @"C:\Path\To\Folder2", @"C:\Path\To\Folder3" };
private void CreateWatchers()
{
foreach (var folder in foldersToWatch)
{
var watcher = new FileSystemWatcher
{
Path = folder,
EnableRaisingEvents = true
};
watcher.Changed += OnChanged; // イベントハンドラを追加
watchers.Add(watcher); // リストに追加
}
}
このコードでは、foldersToWatch
配列に指定されたフォルダをループ処理し、それぞれにFileSystemWatcher
を作成しています。
これにより、大量のフォルダを効率的に監視することができます。
これらの応用例を活用することで、FileSystemWatcher
をより効果的に利用し、特定のニーズに応じた監視機能を実装することが可能です。
まとめ
この記事では、C#のFileSystemWatcher
を使用して複数のフォルダを監視する方法や、実装のベストプラクティス、応用例について詳しく解説しました。
特に、リソース管理やエラーハンドリング、スレッドセーフな実装の重要性を強調し、具体的なサンプルコードを通じて実践的な知識を提供しました。
これを機に、FileSystemWatcher
を活用して、より効率的で安定したファイルシステムの監視機能を実装してみてください。