-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를 사용하여 각 윈폼 클라이언트의 각 스레드에 의해 모니터링 \ 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; 
    } 

그것은 예외를 던지는 사용하는 라인입니다.

인한 문제

나는 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

예외를 throw하는 ** using ** 행입니다. – 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 공유 인 곳에서 이것을 테스트했다. 그것은 문제없이 일했습니다 (나를 위해, 아래 참조).

그러나 :

당신은 (모든 실패 개방 후 100 ms 동안 자고) 시도로 파일을 읽기/열어야합니다. 이것은 FileSystemWatcher가 파일을 감지하지만 이동 (또는 다른 쓰기 작업)이 아직 끝나지 않은 상황에 빠질 수 있기 때문에 파일 만들기/이동이 실제로 준비 될 때까지 기다려야하기 때문입니다.

또는 "실제"파일을 기다리지 않고 "실제"파일을 닫은 후 파일 이동 작업이 만드는 플래그 파일을 기다리십시오.

2)

는 이동 작업이 제대로 파일을 닫습니다하지 않았다 될 수 있을까? 하나의 스크립트 플래그 파일을 생성하고 다른 스크립트가 기다리는 곳

3.)

몇 년 전 내가 (Perl로 작성) 몇 가지 도구를 가지고 있었다.

SMB 2 공유에 약간의 문제가있었습니다. 이것이 SMB 캐싱 때문인 것으로 나타났습니다.

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

이 (클라이언트) 시도

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

참조 :

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 설정은 내가 필요한 것 같다. 나는 재시도 (1000ms의 지연 시간을 갖는 10 번의 재시도, 그것은 정말로 중요하지 않으므로)로 파일을 열지 만 때로는 이것으로도 충분하지 않습니다. 부적절한 코드의 일부만 생략했습니다. – Daniel