FileSystemWatcher 대 폴링으로 파일 변경 사항 확인


152

로컬 또는 네트워크 드라이브의 디렉토리에서 생성되는 파일을 감시하는 응용 프로그램을 설정해야합니다.

FileSystemWatcher타이머에 대한 폴링 또는 폴링이 가장 좋은 옵션 입니까? 과거에는 두 가지 방법을 모두 사용했지만 광범위하게 사용하지는 않았습니다.

두 가지 방법 중 어떤 문제 (성능, 안정성 등)가 있습니까?


3
FileSystemWatcher는 누출이 많은 추상화이며 가장 기본적인 경우에만 의존 할 수는 없습니다. 여기를 참조하십시오 : stackoverflow.com/a/22768610/129130
Stein Åsmul

1
FileSystemWatcher의 안정성 주제에 대한 Raymond Chen (Microsoft 전문가)의 답변에 대한 링크를 추가하고 싶습니다 . 그리고 그의 블로그 : The Old New Thing (예 : FileSystemWatcher 검색).
Stein Åsmul

답변:


105

프로덕션 및 테스트 환경에서 파일 시스템 감시자가 실패하는 것을 보았습니다. 이제는 편의상 고려하지만 신뢰할 수있는 것으로 간주하지 않습니다. 내 패턴은 파일 시스템 감시자와의 변경 사항을 감시하는 것이었지만 누락 된 파일 변경 사항을 포착하기 위해 때때로 폴링합니다.

편집 : UI가있는 경우 사용자에게 폴링 대신 변경 사항을 "새로 고칠 수있는"기능을 제공 할 수도 있습니다. 나는 이것을 파일 시스템 감시자와 결합시킬 것이다.


11
넘어지는 것도 보았습니다. 우리가 사용한 솔루션은 우리 자신의 클래스를 감싸는 것입니다. 래퍼 클래스 ALSO는 타이머를 사용하여 감시자가 여전히 가고 있는지를 확인합니다.
Joel Coehoorn

FileCreated 이벤트에 전달 된 파일을 처리 한 후에는 반환하기 전에 다른 새 파일을 수동으로 확인합니다. 이것은 많은 파일이 한 번에 도착할 때 발생하는 문제를 완화시키는 것으로 보입니다.
John Sibly

4
XP 및 Server 2003에서 로컬 디렉토리와 파일 공유로 테스트했으며 XP 시스템이 현장에 있다고 생각합니다. 로컬 디렉토리와 파일 공유에 문제가있었습니다. 우리가 생각해 낸 가능한 원인 중 하나는 디렉토리에서 짧은 시간에 많은 파일을 복사 / 생성 한 것입니다.
Jason Jackson

5
"어느 날 유령을 보았습니다"라고 말하는 것은 그다지 건설적이고 전문적이지 않습니다. 페이지 아웃 불가 버퍼 오버런에 대한 msdn 문서를 언급하면서 사람들이 스레드를 밟아 문제를 설명 할 수 있습니다. 브렌트의 접근 방식을 사용해 보셨습니까?
v.oddou

4
방금 아마존에서 가스 센서를 구입했는데 제대로 보정하지 않았거나 교정에 대해 알지 못했을 때 많은 사람들이 작동하지 않는다고 말한 것에 놀랐습니다. FileSystemWatcher는 버퍼 크기 그것이 "실패"한 이유라고 거의 보증했다. 이것은 설명서에 쉽게 설명되어 있으며 매우 안정적인 작동을 제공하는 해결 방법이 있습니다 (아래 게시). 이것은 "오류, 무언가가 한 번 작동하지 않았는데 왜 그런지 아무도 모릅니다"라고 말하는 좋은 대답은 아닙니다.
u8it

60

내가 가진 가장 큰 문제는 버퍼가 가득 차면 파일이 누락되는 것입니다. 파이로 쉽게 해결할 수 있습니다. 버퍼를 늘리기 만하면됩니다. 여기에는 파일 이름과 이벤트가 포함되므로 예상되는 파일 수 (시험 및 오류)로 늘리십시오. 페이징 아웃 할 수없는 메모리를 사용하므로 메모리가 부족하면 다른 프로세스가 페이징되도록 할 수 있습니다.

버퍼에 대한 MSDN 기사는 다음과 같습니다. FileSystemWatcher .. ::. InternalBufferSize 속성

MSDN 당 :

디스크로 교체 할 수없는 비 페이징 메모리에서 비롯되므로 버퍼 크기를 늘리면 비용이 많이들므로 버퍼를 가능한 작게 유지하십시오. 버퍼 오버 플로우를 피하려면 NotifyFilter 및 IncludeSubdirectories 특성을 사용하여 원하지 않는 변경 알림을 필터링하십시오.

한 번에 큰 일괄 처리가 예상되므로 16MB를 사용합니다. 잘 작동하고 파일을 놓치지 않습니다.

우리는 또한 하나를 처리하기 전에 모든 파일을 읽습니다. 파일 이름을 안전하게 캐시하여 (이 경우 데이터베이스 테이블에) 가져간 다음 처리하십시오.

파일 잠금 문제의 경우 1 초, 2 초, 4 초 등 파일 잠금이 풀릴 때까지 기다리는 프로세스를 생성합니다. 우리는 절대 폴링 하지 않습니다 . 이것은 약 2 년 동안 오류없이 생산되었습니다.


12
버퍼 오버 플로우? 아, 스택 오버플로를 의미합니다.
TheFlash

1
.NET 3.5 기준 : "버퍼를 4KB 이상으로 설정할 수 있지만 64KB를 초과해서는 안됩니다"
brad

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 공유로 전환 한 이후로 직접 ​​경험하고 있습니다.
Sean

1
내가 아는 것은 아닙니다. 그리고 그것은 단순히 다른 벤더들 사이의 비난 게임 일 것이라고 확신합니다.
chilltemp

1
매핑 된 드라이브에서 파일 시스템 감시자에 문제가 발생했습니다. 맵 연결이 끊겼다가 다시 연결되면 더 이상 파일 감시자가 변경 사항을 발생시키지 않습니다. 쉽게 해결되었지만 여전히 파일 시스템 감시자 IMHO에 대한 공격입니다.
Richard Dorman

11

개인적 FileSystemWatcher으로 프로덕션 시스템을 사용 했으며 정상적으로 작동했습니다. 지난 6 개월 동안 연중 무휴로 운영되는 단일 딸꾹질은 없었습니다. 단일 로컬 폴더 (공유)를 모니터링하고 있습니다. 처리해야하는 파일 조작 수가 비교적 적습니다 (하루에 10 개의 이벤트 발생). 내가 걱정했던 것은 아닙니다. 결정을 다시해야한다면 다시 사용하겠습니다.


7

나는 현재 FileSystemWatcher평균 100 밀리 초마다 업데이트되는 XML 파일을 사용합니다 .

나는만큼이 같은 것을 발견했다 FileSystemWatcher올바르게 구성하면 문제가해서는 안 로컬 파일을.

원격 파일 감시 및 비 Windows 공유에 대한 경험이 없습니다.

본질적으로 불신 FileSystemWatcher하거나 여기에있는 다른 모든 사람들이 나열한 제한 (비 Windows 공유 및 원격 파일 감시)을 직접 경험 하지 않는 한 파일 폴링은 중복되어 오버 헤드가없는 것으로 간주합니다 .


5

나는 설문 조사와 함께 갈 것입니다.

네트워크 문제로 인해 FileSystemWatcher오류 이벤트가 오버로드 될 때도 신뢰할 수 없습니다.


5

FileSystemWatcher네트워크 공유를 사용 하는 데 문제가 있습니다 . 순수한 Windows 환경에 있다면 문제가되지 않지만 NFS 공유를보고 있었고 NFS에 상태가 없기 때문에보고있는 파일이 변경되었을 때 알림이 없었습니다.


나는 같은 문제를 겪었지만 FileSystemWatcher가 NFS를 사용하여 폴더를 공유하는 동일한 Windows 서버에 있었기 때문에 예상치 못한 일이었습니다. NFS와 폴더를 공유한다는 사실은 파일 시스템 감시자가 공유를 사용하여 만든 파일을 원격으로 (예 : 공유를 매핑하는 Linux에서) 볼 수없는 반면 모니터링중인 매우 동일한 폴더에 파일을 쓰면 파일 시스템 감시자가 트리거됩니다. NFS 서버가 하위 계층을 사용하여 파일을 쓰는 것처럼 보이고 파일 시스템 감시자가 실행되지 않는 API 계층은 더 많은 정보를 가지고 있습니까?
Mosè 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가 요구를 완벽하게 충족시키는 경우가 있고 다른 경우에는 폴링 이 필요한 경우가 있습니다 . 불행히도 실제로 "신뢰성"문제에 대해서만 성능 차이 (있는 경우)를 다루는 대답없습니다 . 질문의 해당 부분에 대답 할 수있는 사람이 있습니까?

편집 : nmclean FSW 폴링을 모두 사용한다는 상황이있을 수있는 이유 FSW 폴링을 모두 사용의 유효성의 점은 매우 합리적인 설명을 것으로 보인다 (당신이 관심이 있다면 당신은 코멘트에 토론을 읽을 수 있습니다) 된다 실력 있는. 나를 위해 (그리고 같은 의견을 가진 다른 사람) nmclean을 비추어 주셔서 감사합니다 .


1
파일 변경에 최대한 빨리 응답하려면 어떻게해야합니까? 예를 들어 분당 한 번 폴링하면 파일 변경과 변경 사항을 적용하는 애플리케이션간에 1 분 정도 지연 될 수 있습니다. FSW 이벤트는 아마도 그보다 훨씬 이전에 트리거되었을 것입니다. 따라서 두 가지를 모두 사용하면 가능한 한 적은 지연으로 이벤트를 처리하지만 누락 된 이벤트가있는 경우 선택합니다.
rom99

@ rom99 정확히 내 요점입니다. 경우 상기 FSW는 빠른 응답이 필요한 경우에는 신뢰할 수, 더 빠른 응답, 따라서 응용 프로그램이 신뢰할 수 없습니다가 없습니다 경우이 때문에, 그것을 사용 아무 소용이 없습니다. 스레드에서 짧은 간격으로 폴링을 수행해야합니다. 둘 다를 수행 하면 폴링이 다루는 응답 시간에 허용 오차가 있으므로 폴링 만 사용하는 것은 어떻습니까?
ThunderGr

5
@ThunderGr "따라서 응용 프로그램을 신뢰할 수 없습니다." -대부분의 경우 속도는 안정성의 전제 조건이 아닙니다. 작업 이 완료 되어야 하지만 잠시 기다릴 수 있습니다. 느리고 안정적인 폴링을 빠르고 신뢰할 수없는 FSW 와 결합 하면 항상 신뢰할 수 있고 때로는 빠르며 신뢰할 수 있고 빠르지 않은 응용 프로그램을 얻을 수 있습니다. 지속적인 폴링을 통해 FSW를 제거하고 동일한 최대 응답 시간을 달성 할 수 있지만 이는 나머지 응용 프로그램의 응답 성을 희생하기 때문에 즉각적인 응답이 절대적으로 필요한 경우에만 수행해야합니다.
nmclean

2
이제 가난한 인수 위는? 여전히 디스크 액세스가 필요하지만 필요하기 때문 입니다. 마찬가지로 폴링을 적게 할 수 있습니다. 우리가 여전히 모든 파일을 검사한다고해서 작업량이 동일하다는 것을 의미하지는 않습니다. "폴링은 CPU 시간에 FSW를 사용하여 비싸거나 그렇지 않다"는 설명은 false 입니다. FSW에 "즉시"문제를 오프로드함으로써 우리는 폴링을 우선 순위가 낮은 유휴 작업으로 변경 하여 주어진 시간에 애플리케이션의 사용률을 크게 줄 이면서도 즉시 "치료"를 제공 할 수 있습니다. 폴링만으로는 동일한 균형을 유지할 수 없습니다.
nmclean

9
@nmclean 시간과 노력을 쏟아 부어 주셔서 감사합니다. 당신이 그런 식으로 그것을 넣을 때, 그것은 훨씬 더 의미가 있습니다. 캐시가 특정 문제에 적합하지 않은 경우가 있으므로 FSW (신뢰할 수없는 것으로 입증 된 경우)가 적합하지 않을 수 있습니다. 네가 옳았다는 것이 밝혀졌다. 시간이 너무 많이 걸려서 죄송합니다.
ThunderGr

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

폴링, 특히 TDD 시나리오에서는 폴링을 사용하는 것이 파일의 존재를 조롱 / 스텁하는 것이 훨씬 쉬우 며, 그렇지 않으면 폴링 이벤트가 트리거 될 때 "제어되지 않은"fsw 이벤트에 의존하는 것보다 훨씬 쉽습니다. + fsw 오류에 시달리는 많은 앱에서 작동 한 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.