[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をより効果的に利用し、特定のニーズに応じた監視機能を実装することが可能です。

よくある質問

FileSystemWatcherで監視できる最大フォルダ数は?

FileSystemWatcher自体には、監視できるフォルダ数に明確な上限はありませんが、実際にはシステムリソースやパフォーマンスに依存します。

多くのインスタンスを作成すると、メモリやCPUの使用量が増加し、アプリケーションのパフォーマンスに影響を与える可能性があります。

一般的には、数十から数百のフォルダを監視することが可能ですが、実際の使用状況に応じてテストを行い、最適な数を見つけることが重要です。

監視中にフォルダが削除された場合はどうなる?

監視中のフォルダが削除された場合、FileSystemWatcherはそのフォルダに関連するイベントを発生させません。

具体的には、削除されたフォルダに対するChangedCreatedDeletedイベントは発生しません。

ただし、フォルダが削除された後に新たに作成された場合は、再び監視を開始することができます。

フォルダの存在を確認するためには、定期的にフォルダの状態をチェックする必要があります。

FileSystemWatcherのイベントが発生しない場合の対処法は?

FileSystemWatcherのイベントが発生しない場合、以下の点を確認し、対処することが重要です。

  • EnableRaisingEventsプロパティ: EnableRaisingEventstrueに設定されているか確認します。
  • NotifyFilterプロパティ: 監視する変更の種類が正しく設定されているか確認します。
  • Filterプロパティ: 監視するファイルの種類が正しく設定されているか確認します。
  • アクセス権限: 監視対象のフォルダに対するアクセス権限が適切に設定されているか確認します。
  • バッファサイズ: InternalBufferSizeが小さすぎる場合、イベントが失われることがあります。

必要に応じてバッファサイズを増やします。

  • エラーハンドリング: Errorイベントを監視し、エラーが発生していないか確認します。

これらの点を確認し、必要に応じて設定を見直すことで、FileSystemWatcherのイベントが正常に発生するように調整できます。

まとめ

この記事では、C#のFileSystemWatcherを使用して複数のフォルダを監視する方法や、実装のベストプラクティス、応用例について詳しく解説しました。

特に、リソース管理やエラーハンドリング、スレッドセーフな実装の重要性を強調し、具体的なサンプルコードを通じて実践的な知識を提供しました。

これを機に、FileSystemWatcherを活用して、より効率的で安定したファイルシステムの監視機能を実装してみてください。

当サイトはリンクフリーです。出典元を明記していただければ、ご自由に引用していただいて構いません。

関連カテゴリーから探す

  • URLをコピーしました!
目次から探す