로컬 또는 네트워크 드라이브의 디렉토리에서 생성되는 파일을 감시하는 응용 프로그램을 설정해야합니다.
FileSystemWatcher
타이머에 대한 폴링 또는 폴링이 가장 좋은 옵션 입니까? 과거에는 두 가지 방법을 모두 사용했지만 광범위하게 사용하지는 않았습니다.
두 가지 방법 중 어떤 문제 (성능, 안정성 등)가 있습니까?
로컬 또는 네트워크 드라이브의 디렉토리에서 생성되는 파일을 감시하는 응용 프로그램을 설정해야합니다.
FileSystemWatcher
타이머에 대한 폴링 또는 폴링이 가장 좋은 옵션 입니까? 과거에는 두 가지 방법을 모두 사용했지만 광범위하게 사용하지는 않았습니다.
두 가지 방법 중 어떤 문제 (성능, 안정성 등)가 있습니까?
답변:
프로덕션 및 테스트 환경에서 파일 시스템 감시자가 실패하는 것을 보았습니다. 이제는 편의상 고려하지만 신뢰할 수있는 것으로 간주하지 않습니다. 내 패턴은 파일 시스템 감시자와의 변경 사항을 감시하는 것이었지만 누락 된 파일 변경 사항을 포착하기 위해 때때로 폴링합니다.
편집 : UI가있는 경우 사용자에게 폴링 대신 변경 사항을 "새로 고칠 수있는"기능을 제공 할 수도 있습니다. 나는 이것을 파일 시스템 감시자와 결합시킬 것이다.
내가 가진 가장 큰 문제는 버퍼가 가득 차면 파일이 누락되는 것입니다. 파이로 쉽게 해결할 수 있습니다. 버퍼를 늘리기 만하면됩니다. 여기에는 파일 이름과 이벤트가 포함되므로 예상되는 파일 수 (시험 및 오류)로 늘리십시오. 페이징 아웃 할 수없는 메모리를 사용하므로 메모리가 부족하면 다른 프로세스가 페이징되도록 할 수 있습니다.
버퍼에 대한 MSDN 기사는 다음과 같습니다. FileSystemWatcher .. ::. InternalBufferSize 속성
MSDN 당 :
디스크로 교체 할 수없는 비 페이징 메모리에서 비롯되므로 버퍼 크기를 늘리면 비용이 많이들므로 버퍼를 가능한 작게 유지하십시오. 버퍼 오버 플로우를 피하려면 NotifyFilter 및 IncludeSubdirectories 특성을 사용하여 원하지 않는 변경 알림을 필터링하십시오.
한 번에 큰 일괄 처리가 예상되므로 16MB를 사용합니다. 잘 작동하고 파일을 놓치지 않습니다.
우리는 또한 하나를 처리하기 전에 모든 파일을 읽습니다. 파일 이름을 안전하게 캐시하여 (이 경우 데이터베이스 테이블에) 가져간 다음 처리하십시오.
파일 잠금 문제의 경우 1 초, 2 초, 4 초 등 파일 잠금이 풀릴 때까지 기다리는 프로세스를 생성합니다. 우리는 절대 폴링 하지 않습니다 . 이것은 약 2 년 동안 오류없이 생산되었습니다.
그만큼 FileSystemWatcher
대기 변화의 수를 제공하는 버퍼 오버 플로우하는 경우 또한, 바쁜 시간 동안의 변화를 놓칠 수 있습니다. 이는 .NET 클래스 자체의 제한 사항이 아니라 기본 Win32 인프라의 제한 사항입니다. 경험상이 문제를 최소화하는 가장 좋은 방법은 가능한 빨리 알림을 대기열에서 빼고 다른 스레드에서 처리하는 것입니다.
위의 @ChillTemp에서 언급했듯이 감시자는 Windows가 아닌 공유에서 작동하지 않을 수 있습니다. 예를 들어, 마운트 된 Novell 드라이브에서는 전혀 작동하지 않습니다.
나는 좋은 타협은 누락 된 변경 사항을 포착하기 위해 가끔 투표를하는 것에 동의합니다.
또한 파일 시스템 감시자는 파일 공유에서 신뢰할 수 없습니다. 특히 파일 공유가 Windows 이외의 서버에서 호스팅되는 경우. FSW는 중요한 것에 사용해서는 안됩니다. 또는 가끔 빠진 것이 없는지 확인하기 위해 가끔 투표와 함께 사용해야합니다.
FileSystemWatcher
네트워크 공유를 사용 하는 데 문제가 있습니다 . 순수한 Windows 환경에 있다면 문제가되지 않지만 NFS 공유를보고 있었고 NFS에 상태가 없기 때문에보고있는 파일이 변경되었을 때 알림이 없었습니다.
FSW 와 폴링을 모두 사용 하는 것은 시간과 자원을 낭비하는 것이라고 생각합니다. 숙련 된 개발자가 제안한 것에 놀랐습니다. 폴링을 사용하여 "FSW 누락"을 확인해야하는 경우 FSW를 완전히 버리고 폴링 만 사용할 수 있습니다.
나는 현재 내가 FSW 사용 여부를 결정하려고 또는 내가 개발 프로젝트에 대한 폴링을. 답을 읽으면 FSW가 요구를 완벽하게 충족시키는 경우가 있고 다른 경우에는 폴링 이 필요한 경우가 있습니다 . 불행히도 실제로 "신뢰성"문제에 대해서만 성능 차이 (있는 경우)를 다루는 대답 은 없습니다 . 질문의 해당 부분에 대답 할 수있는 사람이 있습니까?
편집 : nmclean FSW 폴링을 모두 사용한다는 상황이있을 수있는 이유 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 오류에 시달리는 많은 앱에서 작동 한 것입니다.