FileSystemWatcherとポーリングによるファイルの変更の監視


152

ローカルまたはネットワークドライブ上のディレクトリに作成されるファイルを監視するアプリケーションをセットアップする必要があります。

でしょうFileSystemWatcherかポーリングタイマーには最良の選択肢でしょう。私は過去に両方の方法を使用しましたが、広範囲ではありません。

どちらの方法にもどのような問題(パフォーマンス、信頼性など)がありますか?


3
FileSystemWatcherはリークの多い抽象概念であり、最も基本的な場合以外は信頼できません。こちらをご覧ください:stackoverflow.com/a/22768610/129130
SteinÅsmul2014

1
FileSystemWatcherの信頼性のトピックに関するRaymond Chen(Microsoftの専門家)によるこの回答への参照へのリンクを追加したい。そして彼のブログ:The Old New Thing(例えばFileSystemWatcherを検索してください)。
SteinÅsmul18年

回答:


105

実稼働環境とテスト環境でファイルシステムウォッチャーが失敗するのを見てきました。今では便利だと思いますが、信頼できるとは思いません。私のパターンは、ファイルシステムウォッチャーで変更を監視することでしたが、欠落しているファイルの変更を検出するために時々ポーリングします。

編集:UIがある場合は、ポーリングの代わりに変更を「更新」する機能をユーザーに与えることもできます。これをファイルシステムウォッチャーと組み合わせます。


11
転んでも見ました。私たちが使用したソリューションは、独自のクラスをラップすることです。この場合、ラッパークラスはタイマーを使用して、ウォッチャーがまだ実行中であることをチェックします。
Joel Coehoorn、2008年

同様のことを行います。FileCreatedイベントに渡されたファイルを処理したら、戻る前に他の新しいファイルがないか手動で確認します。これにより、一度に到着する多数のファイルで発生する問題が軽減されるようです。
ジョンシブル08年

4
私たちは、XPとServer 2003でローカルディレクトリとファイル共有でテストし、現場にXPマシンを置いたと思います。ローカルディレクトリとファイル共有の両方で問題が発生しました。考えられた原因の1つは、ディレクトリ内に短時間で大量のファイルをコピーまたは作成したことです。
Jason Jackson、

5
「ある日、幽霊を見た」とだけ言っても、あまり建設的でも専門的でもありません。ページアウト不可のバッファオーバーランに関するmsdnドキュメントに言及しているスレッドが問題を説明しているようです。ブレントのアプローチを試してみましたか?
v.oddou 2014

4
Amazonでガスセンサーを購入したところ、明らかに正しく調整されていない、または調整についてさえ知らなかったときに、多くの人がそれが機能しないと言ったのに驚きました。FileSystemWatcherには、そのバッファサイズ。それが「失敗する」理由です。これはドキュメントで簡単に説明されており、非常に信頼できる操作を提供する回避策があります(以下に掲載)。これは、「エラー、一時的に何かがうまくいかなかった、なぜだかわからない...誰もそれに頼るべきではない」と言うだけでは適切な答えではありません。
u8it 2016

60

私が抱えていた最大の問題は、バッファがいっぱいになったときにファイルが見つからないことです。簡単に修正できます。バッファを増やすだけです。ファイル名とイベントが含まれているので、予想されるファイル数(試行とエラー)まで増やしてください。ページアウトできないメモリを使用するため、メモリが不足すると、他のプロセスにページングを強制する可能性があります。

これがバッファに関するMSDNの記事 です。FileSystemWatcher.. ::。InternalBufferSizeプロパティ

MSDNごと:

バッファーサイズの増加は、ディスクにスワップアウトできない非ページメモリが原因であるため、コストがかかるため、バッファーをできるだけ小さくしてください。バッファオーバーフローを回避するには、NotifyFilterプロパティとIncludeSubdirectoriesプロパティを使用して、不要な変更通知を除外します。

一度に大量のバッチが予想されるため、16MBを使用します。正常に動作し、ファイルを見逃すことはありません。

また、1つでも処理を開始する前にすべてのファイルを読み取ります...ファイル名を安全に(この場合はデータベーステーブルに)キャッシュしてから、処理します。

ファイルのロックの問題については、ファイルのロックが解除されるまで1秒、2秒、4回と待機するプロセスを生成します。私たちは決してポーリングしません。これは約2年間エラーなしで生産されています。


12
バッファオーバーフロー?ああ、あなたはスタックオーバーフローを意味します。
TheFlash

1
.NET 3.5以降:「バッファーを4 KB以上に設定できますが、64 KBを超えてはなりません」
ブラッド

9
FileSystemWatcherの最大内部バッファーが64KBの場合、16MBをどのように使用していますか?
BK

1
@ Jarvis、バッファは、処理されるまで送信される情報を保持するように構成された一時的な保存場所です。これは通常、プログラムの再帰のような一部のプロセスでは、到着順にリクエストを処理するためのFIFOまたはキューを意味します。 FILOまたはスタック構造が使用されるものです。この場合、プログラムコールスタックバッファーではなく、イベントキューバッファーを明確に参照しています
MikeT

1
petermeinl.wordpress.com/2015/05/18/tamed-filesystemwatcher この投稿では、標準のFileSystemWatcher(FSW)を使用して実際のアプリケーションでファイルシステムを監視する際に一般的に発生する問題を修正するための強力なラッパーを共有しています。
Kiquenet

35

またFileSystemWatcher、キューに入れられた変更の数が提供されたバッファをオーバーフローすると、ビジー時に変更が失われる可能性もあります。これは.NETクラス自体の制限ではなく、基盤となるWin32インフラストラクチャの制限です。私たちの経験では、この問題を最小限に抑える最善の方法は、通知をできるだけ早くデキューして、別のスレッドで処理することです。

上記の@ChillTempで述べたように、ウォッチャーはWindows以外の共有では機能しない場合があります。たとえば、マウントされたNovellドライブではまったく機能しません。

見落とされた変更をピックアップするために時々投票を行うことが、適切な妥協案であることに同意します。


4
ファイルシステムウォッチャーは、多くのイベントを連続して発生させることができます。イベントハンドラが実行されるのと同じくらい早く実行できない場合、最終的にハンドラはイベントをフロアにドロップし始め、見落とします。
ブレントロックウッド

17

また、ファイルシステムウォッチャーは、ファイル共有では信頼できないことに注意してください。特に、ファイル共有がWindows以外のサーバーでホストされている場合。FSWは重要なものには使用しないでください。または、何も見落とされていないことを確認するために時々ポーリングを使用する必要があります。


3
Microsoftは、Windows以外のファイル共有では信頼性がないことを認識していますか?Windows共有からLinuxベースのSMB共有に切り替えて以来、私たちは確かにこれを直接体験しています。
ショーン

1
私が知っていることではありません。そして、それは単に異なるベンダー間の非難のゲームになると確信しています。
chilltemp

1
マップされたドライブのファイルシステムウォッチャーで問題が発生しました。マップが切断されてから再接続された場合、File Watcherは変更を発生させなくなります。簡単に解決できますが、ファイルシステムウォッチャーのIMHOに対するストライキはまだです。
Richard Dorman

11

個人的に、私はFileSystemWatcher本番システムでを使用しましたが、問題なく動作しました。過去6か月間、1日24時間年中無休の一時的な問題は発生していません。単一のローカルフォルダー(共有)を監視しています。処理する必要があるファイル操作は比較的少数です(1日あたり10個のイベントが発生します)。それは私が今まで心配する必要があったものではありません。決定を下さなければならなかった場合は、もう一度使用します。


7

私は現在FileSystemWatcher、平均で100ミリ秒ごとに更新されるXMLファイルでを使用しています。

FileSystemWatcherが正しく設定されている限り、ローカルファイルに問題が発生することはありません。

リモートファイルウォッチやWindows以外の共有の経験はありません。

あなたが本質的に不信感を持っているFileSystemWatcherか、ここにいる他のすべての人がリストしている制限(Windows以外の共有、およびリモートファイル監視)を直接経験していない限り、ファイルのポーリングは冗長でオーバーヘッドの価値がないと考えます。


5

私は投票に行きます。

ネットワークの問題により、FileSystemWatcher(エラーイベントが過負荷になった場合でも)が信頼できなくなります。


5

FileSystemWatcherネットワーク共有での使用で問題が発生しました。純粋なWindows環境の場合は問題ないかもしれませんが、NFS共有を監視していました。NFSはステートレスであるため、監視しているファイルが変更されたときに通知がありませんでした。


同じ問題が発生しましたが、FileSystemWatcherがNFSを使用してフォルダーを共有する同じWindowsサーバー上にあったため、予期せぬ事態でした。フォルダーをNFSで共有するという事実により、filesystemwatcherは共有を使用してリモートで(つまり、共有をマップするLinuxから)作成されたファイルを表示しませんが、監視下のまったく同じフォルダーにファイルを書き込むと、filesystemwatcherがトリガーされます。NFSサーバーが下位層を使用してファイルを書き込むように見え、filesystemwatcherが使用されていないことをトリガーするAPI層、誰もがより多くの情報を持っていますか?
モーゼBottacini

3

ネットワークドライブのFSWでいくつかの大きな問題がありました。ファイルを削除すると、常にエラーイベントがスローされ、削除イベントはスローされませんでした。解決策が見つからなかったので、今はFSWを避けてポーリングを使用しています。

一方、作成イベントは問題なく機能したため、ファイルの作成のみを監視する必要がある場合は、FSWに進むことができます。

また、共有されているかどうかにかかわらず、ローカルフォルダーにはまったく問題がありませんでした。


3

イベントメソッドからできるだけ早く戻り、別のスレッドを使用して、問題を解決しました:

private void Watcher_Created(object sender, FileSystemEventArgs e)
{
    Task.Run(() => MySubmit(e.FullPath));
}

2

私の意見では、FSW ポーリングの両方を使用することは時間とリソースの浪費であり、経験豊富な開発者がそれを提案することに驚いています。ポーリングを使用して「FSWミス」をチェックする必要がある場合は、当然、FSWをすべて破棄して、ポーリングのみを使用できます。

現在、開発中のプロジェクトにFSWを使用するかポーリングを使用するかを決定しようとしています。回答を読むと、FSWがニーズを完全にカバーしている場合もあれば、ポーリングが必要な場合もあることは明らかです。残念ながら、実際にはパフォーマンスの違い(存在する場合)については回答なく、「信頼性」の問題についてのみ対処しています。質問のその部分に答えることができる人はいますか?

編集: FSWとポーリングの両方を使用することの妥当性に関するnmcleanのポイント(興味があれば、コメントの議論を読むことができます)は、FSWとポーリングの両方を使用する状況があり得る理由が非常に合理的な説明のようです効率的です。nmclean、私(および同じ意見を持つ人)に光を当ててくれてありがとう


1
ファイルの変更にできるだけ迅速に対応したい場合はどうでしょうか?たとえば、毎分1回ポーリングする場合、ファイルの変更とアプリケーションによる変更の取得との間に1分の遅延が生じる可能性があります。FSWイベントはそれよりずっと前にトリガーされると考えられます。したがって、両方を使用することで、できるだけ少ない遅延でイベントを処理するだけでなく、見逃したイベントがある場合はそれを取得します。
rom99 2014年

@ rom99まさに私のポイント。迅速な対応が必要な場合にFSWの信頼性が低いと、迅速な対応ができない場合があり、アプリケーションの信頼性が低くなるため、FSWを使用しても意味がありません。スレッド内の短い間隔でのポーリングは、実行する必要があるものです。両方を実行することにより、ポーリングがカバーする応答時間に許容範囲があることを意味します。それでは、ポーリングのみを使用しないのはなぜですか?
ThunderGr 2014年

5
@ThunderGr 「したがって、アプリケーションは信頼できなくなります。」-多くの場合、速度は信頼性の前提条件ではありません。作業完了する必要ありますが、しばらく待つことができます。低速で信頼性の高いポーリングを高速で信頼性の低い FSW と組み合わせると、常に信頼性が高く時には高速なアプリケーションが得られます。FSWを削除して一定のポーリングを行うことで同じ最大応答時間を達成できますが、これはアプリケーションの残りの部分の応答性を犠牲にするため、即時の応答が絶対に必要な場合にのみ実行する必要があります。
nmclean 2014年

2
さて、上記はなぜ不十分な議論なのでしょうか?まだディスクアクセスが必要ですが、必要なディスク数が少ないためです。同様に、投票数を減らすことができます。すべてのファイルをチェックしているからといって、ワークロードが同じであるとは限りません。「ポーリングはFSWを使用する場合、CPU時間に負荷がかかるかどうか」という文は誤りです。「即時性」の懸念をFSWにオフロードすることで、ポーリングをアイドルで優先度の低いタスクに変更できます。これにより、即時性の「扱い」を提供しながら、アプリケーションのビジー性が大幅に削減されます。ポーリングだけで同じバランスを達成することはできません。
nmclean 2014年

9
@nmclean時間と労力をかけて、これまでのやり方でこれを明確にしていただきありがとうございます。そのように置くと、それは確かにはるかに理にかなっています。キャッシュが特定の問題に適していない場合があるように、FSW(信頼できないことが判明した場合)は適さない場合があります。あなたはずっと正しかったことがわかります。届くまでに時間がかかってごめんなさい。
ThunderGr 2014年

1

変更の代わりに作成イベントを操作するための実用的なソリューション

コピー、切り取り、貼り付け、移動も可能です。

class Program
{        

        static void Main(string[] args)
        {
            string SourceFolderPath = "D:\\SourcePath";
            string DestinationFolderPath = "D:\\DestinationPath";
            FileSystemWatcher FileSystemWatcher = new FileSystemWatcher();
            FileSystemWatcher.Path = SourceFolderPath;
            FileSystemWatcher.IncludeSubdirectories = false;
            FileSystemWatcher.NotifyFilter = NotifyFilters.FileName;   // ON FILE NAME FILTER       
            FileSystemWatcher.Filter = "*.txt";         
             FileSystemWatcher.Created +=FileSystemWatcher_Created; // TRIGGERED ONLY FOR FILE GOT CREATED  BY COPY, CUT PASTE, MOVE  
            FileSystemWatcher.EnableRaisingEvents = true;

            Console.Read();
        }     

        static void FileSystemWatcher_Created(object sender, FileSystemEventArgs e)
        {           
                string SourceFolderPath = "D:\\SourcePath";
                string DestinationFolderPath = "D:\\DestinationPath";

                try
                {
                    // DO SOMETING LIKE MOVE, COPY, ETC
                    File.Copy(e.FullPath, DestinationFolderPath + @"\" + e.Name);
                }
                catch
                {
                }          
        }
}

静的ストレージを使用したファイル属性変更イベント中のこのファイルウォッチャーの解決策

class Program
{
    static string IsSameFile = string.Empty;  // USE STATIC FOR TRACKING

    static void Main(string[] args)
    {
         string SourceFolderPath = "D:\\SourcePath";
        string DestinationFolderPath = "D:\\DestinationPath";
        FileSystemWatcher FileSystemWatcher = new FileSystemWatcher();
        FileSystemWatcher.Path = SourceFolderPath;
        FileSystemWatcher.IncludeSubdirectories = false;
        FileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite;          
        FileSystemWatcher.Filter = "*.txt";         
        FileSystemWatcher.Changed += FileSystemWatcher_Changed;
        FileSystemWatcher.EnableRaisingEvents = true;

        Console.Read();
    }     

    static void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
    {
        if (e.Name == IsSameFile)  //SKIPS ON MULTIPLE TRIGGERS
        {
            return;
        }
        else
        {
            string SourceFolderPath = "D:\\SourcePath";
            string DestinationFolderPath = "D:\\DestinationPath";

            try
            {
                // DO SOMETING LIKE MOVE, COPY, ETC
                File.Copy(e.FullPath, DestinationFolderPath + @"\" + e.Name);
            }
            catch
            {
            }
        }
        IsSameFile = e.Name;
    }
}

これは、この複数のトリガーイベントの問題の回避策です。


0

特に「制御されていない」fswイベントに依存するよりも、ポーリングイベントがトリガーされたときにファイルの存在をモック/スタブ化する方がはるかに簡単なので、特にTDDシナリオではポーリングを使用すると思います。+ fswエラーに悩まされていた多くのアプリに取り組んできたことに。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.