-1

背景FileSystemWatcherは、ネットワーク共有に利用可能なファイルを報告しますが、ファイルが見つかりません

私は4つのサブフォルダを共有フォルダ\\Server\Shareを持つサーバーあります

  • OutboundFinal
  • OutboundStaging
  • をInboundFinal
  • InboundStaging

すべてのフォルダは同じ物理ディスクとパーティションに存在し、接合点は使用されません。

また、この共有にファイルを書き込み、読み込む複数のWinFormsクライアント(最大10個)があり、各クライアントは複数のスレッド(最大5個)で作業しています。ファイルは\\Server\Share\OutboundStagingフォルダにクライアント(最大50個のスレッド)によって書き込まれます。各ファイルにはGUIDの名前があるため、上書きはありません。ファイルが完全に書き込まれると、そのファイルはクライアントによって\\Server\Share\OutboundFinalフォルダーに移動されます。同じサーバー上で実行されているWindowsサービスは、それを取り出して削除し、処理した後、同じ名前のファイルを\\Server\Share\InboundStagingフォルダに書き込みます。ファイルが完全に書き込まれると、サービスによって\\Server\Share\InboundFinalフォルダーに移動されます。

この\\サーバー\共有\ InboundFinalフォルダが特定のスレッドが\サーバー\共有に見ることを期待ファイルのGUIDのファイル名に設定されているFileSystemWatcher.WaitForChanged(WatcherChangeTypes.Changed | WatcherChangeTypes.Created, timeOut); FileSystemWatcher.Filterを使用して、各WinFormsのクライアントの各スレッドによって監視されている\ InboundFinalフォルダに格納されているため、FileSystemWatcherはフォルダ内に特定のファイルが表示されるまで待機します。

FileSystemWatcherについて、いくつかの質問を読んで、UNCシェアの変更を報告していません。しかしこれは私の場合ではありません。

FileSystemWatcher fileWatcher = new FileSystemWatcher(); 
    fileWatcher.Path = InboundFinalFolder; 
    fileWatcher.Filter = GUIDFileName; // contains full UNC path AND the file name 
    fileWatcher.EnableRaisingEvents = true; 
    fileWatcher.IncludeSubdirectories = false; 
    var res = fileWatcher.WaitForChanged(WatcherChangeTypes.Changed | WatcherChangeTypes.Created, timeOut); 
    if (!fileWatcher.TimedOut) 
    { 
     using (FileStream stream = fi.Open(FileMode.Open, FileAccess.Read, FileShare.Read)) { 
     byte[] res = new byte[stream.Length]; 
     stream.Read(res, 0, stream.Length); 
     return res; 
    } 

それが例外をスロー用いたラインです:

私が使用するコードは次のようになります。

PROBLEM

私はfileWatcher.WaitForChangedが適切なGUIDの名前のファイルが\\Server\Share\InboundFinalフォルダ内にある場合にのみに行くだろうことを前提としています。これは、FileSystemWatcherがローカルフォルダでどのように動作するのか、ネットワークを介してアクセスされるファイル共有(ローカルファイルは共有を介してアクセスされた場合でも動作する傾向があります)では動作しません。 FileSystemWatcherは、スレッドが待機しているファイルがFileSystemWatcher \\Server\Share\InboundFinalフォルダにあることを報告します。しかし、ファイルを読み込もうとすると、FileNotFoundExceptionが発生します。読み取りスレッドは、ファイルが読み取られるまで3〜15秒待たなければなりません。私はRead共有のFileStreamでファイルを開こうとします。

この現象の原因は何ですか?どのように私はそれを回避するのですか?理想的には、FileSystemWatcher.WaitForChanged(WatcherChangeTypes.Changed | WatcherChangeTypes.Created, timeOut);は、ファイルの読み取りが可能な場合やタイムアウトが発生した場合にのみ実行を継続する必要があります。

+0

FileNotFoundExceptionはかなり基本的です。標準的な間違いは、ファイルを開くためにGUIDFileNameを使用することです。十分ではありませんが、完全なパスではありません。テスト時には偶然に動作し、サーバー上では動作しません。また、アンチマルウェアを無効にして試してみてください。スキャンしている間にファイルを隠していると思われる場合に備えて、これをお勧めします。あなたは実際に失敗したコードを投稿しなかったので、これらは推測です。 –

+0

GUIDFileNameプロパティには、完全なUNCパスとGUIDファイル名が含まれています。申し訳ありませんが、私は私の質問でコードスニペットを編集して明確にしました。 – Daniel

+0

例外をスローするのは** usingの** lineです。 – Daniel

答えて

0

FileSystemWatcherは悪い評判を持っていますが、実際には、それは...

1悪くはないです。)

コードサンプルがコンパイルされません。私はこれを試しました:

FileSystemWatcher fileWatcher = new FileSystemWatcher(); 
fileWatcher.Path = "X:\\temp"; 
fileWatcher.Filter = "test.txt"; 
fileWatcher.EnableRaisingEvents = true; 
fileWatcher.IncludeSubdirectories = false; 

var res = fileWatcher.WaitForChanged(WatcherChangeTypes.Changed | 
           WatcherChangeTypes.Created, 20000); 
if (!res.TimedOut) 
{ 
    FileInfo fi = new FileInfo(Path.Combine(fileWatcher.Path, res.Name)); 

    using (FileStream stream = fi.Open(FileMode.Open, FileAccess.Read, FileShare.Read)) 
    { 
     byte[] buf = new byte[stream.Length]; 

     stream.Read(buf, 0, (int)stream.Length); 
    } 

    Console.WriteLine("read ok"); 
} 
else 
{ 
    Console.WriteLine("time out"); 
} 

私はX:がSMB共有であることをテストしました。それは問題なく働いた(私にとっては、以下を参照)。

しかし:

あなたは(すべての失敗したオープン後100msの間眠って)再試行でファイルを読み込む/開く必要があります。これは、FileSystemWatcherがファイルを検出するが、移動(または別の書き込み操作)がまだ終了していない状況に遭遇する可能性があるため、ファイルの作成/移動が実際に準備ができるまで待つ必要があるからです。

「本当の」ファイルを待つのではなく、「実際の」ファイルを閉じた後にファイルの移動タスクが作成するフラグファイルを待つ必要があります。

2)

それが移動タスクが正しくファイルを閉じていなかったということだろうか?

3)

何年か前、私は1つのスクリプトがフラグファイルを作成し、別のスクリプトがそれを待っていたperlで書かれたいくつかのツールを()でした。

私はSMB 2シェアでいくつかの厄介な問題を抱えていました。私はこれがSMBキャッシングのためであることを知りました。

は、(クライアント上)これを試してみてください

https://bogner.sh/2014/10/how-to-disable-smb-client-side-caching/

File open fails initially when trying to open a file located on a win2k8 share but eventually can succeeed

https://technet.microsoft.com/en-us/library/ff686200.aspx

を参照してください:

Windows Registry Editor Version 5.00 

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\LanmanWorkstation\Parameters] 

"DirectoryCacheLifetime"=dword:00000000 
"FileNotFoundCacheLifetime"=dword:00000000 

保存このdisablecache.regし、実行にregeditをdisablecacとしてhe.reg

その後、再起動します。

+0

あなたの答えが私の場合に役立つ豊富な情報を持っているので、私はそれがなぜ落選したのか分かりません(私はそれを修正しました)。実際、この答えは私の問題に関連する多くの事柄を持っています。 – Daniel

+0

答えをありがとう。そのFileNotFoundCacheLifetimeの設定はちょうど私が必要としているようです。私は再試行(1000ミリ秒の遅れを伴う10回の再試行、それは本当に私にとって問題ではない)でファイルを開きますが、時にはそれでも十分ではありません。私はちょうどそれが無関係だったようにコードのその部分を省いた。 – Daniel

関連する問題