ローカルまたはネットワーク ドライブの両方でディレクトリに作成されるファイルを監視するアプリケーションをセットアップする必要があります。
FileSystemWatcher
またはタイマーのポーリングが最適なオプションでしょうか。私は過去に両方の方法を使用しましたが、広範囲には使用していません。
どちらの方法にもどのような問題 (パフォーマンス、信頼性など) がありますか?
ローカルまたはネットワーク ドライブの両方でディレクトリに作成されるファイルを監視するアプリケーションをセットアップする必要があります。
FileSystemWatcher
またはタイマーのポーリングが最適なオプションでしょうか。私は過去に両方の方法を使用しましたが、広範囲には使用していません。
どちらの方法にもどのような問題 (パフォーマンス、信頼性など) がありますか?
実稼働環境とテスト環境でファイル システム ウォッチャーが失敗するのを見てきました。今では便利だと思いますが、信頼できるとは思いません。ファイル システム ウォッチャーで変更を監視するのが私のパターンですが、ときどきポーリングして欠落しているファイルの変更をキャッチします。
編集: UI がある場合は、ユーザーがポーリングの代わりに変更を「更新」できるようにすることもできます。これをファイルシステムウォッチャーと組み合わせます。
私が抱えていた最大の問題は、バッファがいっぱいになったときにファイルが見つからないことです。簡単に修正できます。バッファを増やすだけです。これにはファイル名とイベントが含まれていることに注意してください。そのため、予想されるファイル数まで増やしてください (試行錯誤)。ページアウトできないメモリを使用するため、メモリが少なくなると、他のプロセスが強制的にページングされる可能性があります。
buffer に関する MSDN の記事は次のとおり です。 FileSystemWatcher..::.InternalBufferSize プロパティ
MSDN によると:
バッファー サイズを大きくすると、ディスクにスワップ アウトできない非ページ メモリから発生するため、コストがかかるため、バッファーをできるだけ小さくしてください。バッファ オーバーフローを回避するには、NotifyFilter プロパティと IncludeSubdirectories プロパティを使用して、不要な変更通知を除外します。
一度に大量のバッチが予想されるため、16MB を使用します。正常に動作し、ファイルを見逃すことはありません。
また、1 つでも処理を開始する前にすべてのファイルを読み取ります...ファイル名を安全にキャッシュして (この場合はデータベース テーブルに) 取得してから処理します。
ファイルのロックの問題については、ファイルのロックが解除されるのを 1 秒、2 秒、4 秒などと待機するプロセスを生成します。投票することはありません。これは、約 2 年間、エラーなく生産されています。
キューに入れられた変更のFileSystemWatcher
数が提供されたバッファをオーバーフローした場合、 はビジー時にも変更を見逃す可能性があります。これは、.NET クラス自体の制限ではなく、基盤となる Win32 インフラストラクチャの制限です。私たちの経験では、この問題を最小限に抑える最善の方法は、通知をできるだけ早くデキューし、別のスレッドで処理することです。
上記の @ChillTemp で述べたように、ウォッチャーは Windows 以外の共有では機能しない場合があります。たとえば、マウントされた Novell ドライブではまったく機能しません。
折に触れてポーリングを行い、見逃された変更を検出するのが良い妥協案であることに同意します。
また、ファイル システム ウォッチャーはファイル共有では信頼できないことに注意してください。特に、ファイル共有が Windows 以外のサーバーでホストされている場合。FSW は、重要なことには使用しないでください。または、不定期のポーリングで使用して、何も見逃していないことを確認する必要があります。
個人的にはFileSystemWatcher
、実稼働システムで を使用しましたが、問題なく動作しました。過去 6 か月間、24 時間 365 日稼働で問題が発生したことは一度もありません。単一のローカル フォルダー (共有されている) を監視しています。処理する必要があるファイル操作の数は比較的少ないです (1 日あたり 10 個のイベントが発生します)。それは私が今まで心配しなければならなかったことではありません。決定をやり直す必要がある場合は、もう一度使用します。
私は現在FileSystemWatcher
、平均して 100 ミリ秒ごとに更新される XML ファイルで を使用しています。
FileSystemWatcher
が適切に構成されている限り、ローカルファイルで問題が発生することはありません。
リモート ファイル ウォッチングや非 Windows 共有の経験はありません。
ファイルをポーリングすることは冗長であり、オーバーヘッドの価値がないと考えます。ただし、本質的に信頼していないFileSystemWatcher
か、ここに記載されている制限 (Windows 以外の共有、およびリモート ファイル監視) を直接経験したことがある場合を除きます。
FileSystemWatcher
ネットワーク共有での使用で問題が発生しました。純粋な Windows 環境にいる場合は問題にならないかもしれませんが、私は NFS 共有を監視していました。NFS はステートレスであるため、監視しているファイルが変更されたときに通知がありませんでした。
私は投票に行きます。
ネットワークの問題により、 のFileSystemWatcher
信頼性が低下します (エラー イベントが過負荷になっている場合でも)。
ネットワーク ドライブの FSW には大きな問題がありました。ファイルを削除すると、常にエラー イベントが発生し、削除されたイベントは発生しませんでした。解決策が見つからなかったため、FSW を使用せずにポーリングを使用するようになりました。
一方、作成イベントは正常に機能したため、ファイルの作成のみを監視する必要がある場合は、FSW を使用できます。
また、共有されているかどうかに関係なく、ローカル フォルダーにはまったく問題はありませんでした。
私の意見では、FSWとポーリングの両方を使用することは時間とリソースの無駄であり、経験豊富な開発者がそれを提案していることに驚いています。「FSWミス」をチェックするためにポーリングを使用する必要がある場合は、当然、FSWを完全に破棄してポーリングのみを使用できます。
現在、開発中のプロジェクトでFSW を使用するかポーリングを使用するかを決定しようとしています。回答を読むと、FSW がニーズを完全にカバーする場合もあれば、ポーリングが必要な場合もあることは明らかです。残念ながら、 「信頼性」の問題のみで、パフォーマンスの違い(ある場合)に実際に対処した答えはありません。質問のその部分に答えられる人はいますか?
EDIT : FSW とポーリングの両方を使用することの有効性に関する nmcleanのポイント (興味がある場合は、コメントで説明を読むことができます) は、FSW とポーリングの両方を使用する状況が発生する可能性がある理由を非常に合理的に説明しているようです。効率的。私(および同じ意見を持つ他の人)のためにそれを明らかにしてくれてありがとう、nmclean。
変更の代わりに作成イベントを操作するための実用的なソリューション
コピー、切り取り、貼り付け、移動にも。
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;
}
}
これは、複数のトリガー イベントの問題に対する回避策です。
特にTDDシナリオでは、ポーリングイベントがトリガーされたときに、より「制御されていない」fswイベントに依存するよりも、ファイルの存在をモック/スタブする方がはるかに簡単であるため、ポーリングを使用すると思います。+ fswエラーに悩まされていた多くのアプリに取り組んできたことに。