2011-02-11 2 views
5

이 문제를 해결하는 가장 좋은 방법은 무엇입니까?C# - 폴더 삭제시 파일 시스템 이벤트 예측

나는 파일 및 폴더의 사용자 변경 사항을 알려주는 FileSystemWatcher입니다. 또한 하위 디렉토리도 감시됩니다. 동일한 디렉토리에서 내 프로그램이 때때로 변경됩니다. FileSystemWatcher에서 이러한 프로그램 변경에 대한 이벤트를 검색하지 않으려합니다.

첫 번째 구현은 예상 이벤트를 추가 할 수있는 목록이었습니다. 파일 시스템 이벤트가 발생하면 목록을 확인한 후 목록을 무시합니다. 이것은 매우 강력하게 들리지는 않지만 작동하는 것처럼 보입니다.

이제 실제 문제가 발견되었습니다.
D :는 (은) FileSystemWatcher입니다.
다음과 같은 두 개의 폴더가 있습니다. D : \ folder1 \ folder2
이제 응용 프로그램과 함께 folder1 (folder2 포함)을 삭제하려고합니다. 그래서 D : \ folder1을 삭제 목록에 넣습니다. 그런 다음 Directory.Delete(@"D:\folder1", true)과 같은 것을 호출합니다. 이제 folder1을 예외로 삭제할 수 없음을 알았습니다. 내 목록에서 삭제 항목을 제거하지만 folder2는 이미 삭제되었고 그의 FileSystemEvent를 얻습니다. 그래서 D : \ folder1 \ folder2에 대한 FileSystem 이벤트를 얻습니다. 내 프로그램은 이제 사용자가이 폴더를 삭제하고 잘못된 일을하고 있다고 생각합니다.

는 지금 몇 가지 아이디어를 가지고 :

1.) 재귀 적으로 그 자체로 모든 파일과 모든 폴더를 삭제하여 폴더를 삭제합니다. 이것으로 모든 하위 폴더에 들어가서 자신의 목록 항목을 제출합니다. 이미 구현했지만 매우 느리다.

2.) 내 목록을 쓸모 없게 만들려면 FileSystemWatcher에 영리한 필터를 사용하는 것이 더 좋은 방법 일 수 있습니까?

3) 모든 것을 삭제할 수있는 경우에만 디렉토리 트리 만 삭제할 수 있습니다. 그래서 실패하면 나는 모든 것을 가지고 있으며 모든 것이 삭제되지 않는다면. 이것은 나를위한 가장 우아한 해결책 인 것처럼 보이지만 이것이 가능할 지 아무 생각도하지 않습니까?

4.) 소프트웨어로 모든 파일과 폴더를 독점적으로 잠글 수 있습니까? 이게 괜찮 았으면 한 번만 삭제 명령으로 삭제할 수 있어야합니다.

다른 추가 솔루션을 이용할 수 있습니다.

편집 1은 좀 더 명확하게하기 :

난 단지 폴더에 사용자 작업 "을 참조하십시오"하고 싶다. 여기에서 내 프로그램의 것들을 조작한다면 나는이 사건을보고 싶지 않다.

폴더가 잠겨서 삭제할 수없는 경우 하위 폴더에 대한 이벤트가 생깁니다.

나는 영어가 모국어가 아니기 때문에 영어로 설명하기가 쉽지 않습니다.).

편집 2 :

5.) 어쩌면 정의 된 프로세스에서 FileSystemWatcher의 모든 이벤트를 필터링 할 수 있습니다?

+0

물건을 예측하는 데있어 당신의 질문은 어디에 있습니까? –

+0

필자가 작성한 목록은 나중에 FileSystemWatcher에서 가져와야하는 예상 이벤트가 포함되어 있기 때문에 예측입니다. 그것은 이렇게 작동합니다 : 1.) 목록에서 기억 2.) 파일/폴더 조작 3.) 목록으로 이벤트 무시 – fpdragon

+0

진지하게, 나는 이것을 얻지 못하고 있습니다. 어떤 사건이 예상됩니까? 대신에 어떤 사건이 있습니까? 어떤 예외가 있습니까? 이 점들로 질문을 업데이트하십시오. –

답변

0

좋아하는 이벤트를 놓치지 않을 것입니다 그런 식으로처럼 그렇게하면 문제의 내 솔루션입니다 하나는 파일 삭제 용이고 다른 하나는 폴더 삭제 용입니다.

파일 목록 항목에 시간 초과가 없습니다. 파일을 삭제하면 목록 항목이 생성되고 예상 된 삭제 이벤트가 발생하면 이전과 같이 항목이 제거됩니다.

폴더 목록 항목을 만든 후 시간 제한이 없습니다. 특별한 방법으로 1 초 후에 수동으로 명령을 내릴 수 있습니다. 폴더를 삭제하면 deleteFolder 목록 항목이 추가됩니다. 이 폴더 또는 파일 또는 하위 폴더 또는 하위 폴더 파일의 모든 삭제 이벤트는이 폴더 항목 삭제로 인해 무시됩니다. 삭제가 끝나면 deleteFolder 항목에 대한 시간 제한을 설정합니다. 만약 delete가 예외를 던지면 나는 똑같이한다. 그래서 나는 모든 이벤트를 1 초 후에 얻길 기대합니다. delete 명령이 작동하는지 여부에 따라 모든 이벤트를 무시합니다. 이 후 deleteFolder 목록 항목이 삭제됩니다.

제한 사항 : 1. 모든 삭제 이벤트는 삭제가 발생한 후 1 초가되어야합니다. 2.
폴더를 만들 다시
덜 다시 (타임 아웃이 삭제 폴더 목록 항목의 완료되지 않은) 일초
삭제 폴더

대기
삭제 폴더 (완료) :이 같은 폴더를 삭제 할 수 없습니다

희망이 있으면 누군가도 매우 복잡합니다 ^^

2

저는 최근에 이런 일을했습니다. 트릭은 목록에 폴더 이름이있는 곳을 '목록'으로 인식하고, 삭제 이벤트가 예상되는 경우 해당 폴더 내의 모든 이벤트를 삭제하고 폴더 자체 인 경우에만 예측 목록에서 제거합니다.

너무 많은 이벤트가 연속적으로 발생하면 FileSystemWatcher 버퍼가 가득차는 데 문제가 발생할 수 있음을 경고해야합니다. 이 경우 Error 이벤트가 발생하며 전체 일정을 알리지 못합니다. 예측 목록에서 이벤트를 수신 할 때 항목을 제거하는 경우 무시할 이벤트가 버퍼 오버 플로우로 인해 절대로 수신되지 않았기 때문에 향후 이벤트를 무시할 위험이 있습니다. 항목이 목록에서 절대로 제거되지 않기 때문에 매우 커질 수도 있습니다.

안정적으로이 방법을 찾지 못했지만 FileSystemWatcher 버퍼의 크기를 최대로 설정하여 어느 정도 완화 할 수는 있습니다.

편집 : 또한 매우 중요합니다 : 돌아올 핸들러 같은 Control 또는 Form로, ISynchronizeInvoke를 구현하는 객체에있는 경우가 아니면 (다른 스레드에서 그렇게, 당신이 당신의 Control/FormSynchronizingObject를 설정 한 이벤트 이것은 잠재적 인 경쟁 조건을 고려하여 목록을 유지하는 방법을 매우 신중하게해야한다는 것을 의미합니다. 나는 여전히이 문제로 고민하고 있는데, 코드가 오류 이벤트를 수신하면 예측 목록을 플러시하지만, 이벤트, 오류가 이미 발생하여 처리 한 이후의 다른 변경 이벤트가 발생하지 않도록해야합니다.

+0

매우 흥미 롭습니다 ... 고맙습니다. 이 FileSystemWatcher 버퍼의 크기가 얼마나되는지 아십니까? 또한 목록 항목에 대해 예상 수명을 구현하여이를 조금 정리하려고 시도했지만 FileSystem 이벤트 (최악의 경우)가 얼마나 빨리 발생합니까? 당신이 나를 최신 상태로 유지하고 당신의 경험을 말해 줄 수 있다면 좋을 것입니다. 1 + – fpdragon

+0

만약 내가이 인생을 구현했을 거라고 그것은 폴더 삭제에 대한 정규식을 사용할 수 있고 그냥 목록 항목 수명이 될 수 있도록 튼튼한 것입니다. – fpdragon

+1

'FileSystemWatcher'는'InternalBufferSize' 속성을 가지고 있습니다. 기본값은 8k이지만 64k까지 올라갈 수 있습니다. http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.internalbuffersize.aspx – Flynn1179

1

버퍼 오버플로에 관한 가장 좋은 방법은 다음과 같습니다. 해결은 다른 스레드의 이벤트에 대한 응답으로 작업을 수행하는 것입니다.

그냥 삭제 명령 : 나는이 목록을 구현

나는이

// Queue of changed paths. 
private readonly Queue<string> mEventQueue = new Queue<string>(); 

// add this as handler for filesystemwatcher events 
public void FileSystemEvent(object source, FileSystemEventArgs e) { 
    lock (mEventQueue) { 
     if (!mEventQueue.Contains(e.FullPath)) { 
      mEventQueue.Enqueue(e.FullPath); 
      Monitor.Pulse(mEventQueue); 
     } 
    } 
} 

// start this on another thread 
public void WatchLoop() { 
    string path; 
    while (true) { 
     lock (mEventQueue) { 
      while (mEventQueue.Count == 0) 
       Monitor.Wait(mEventQueue); 
      path = mEventQueue.Dequeue(); 
      if (path == null) 
       break; 
     } 
     // do whatever you want to do 
    } 
} 

여기

+0

고마워요 ... 저는 이미 비슷한 것을 가지고 있습니다. 나는 PC에 과부하가 걸린 상황을 생각하고 있었다. 가능한지 확실하지 않지만 기본 FileSystemWatcher는 약 500 개의 항목을 저장할 수 있습니다. 이는 작업자 스레드가 있고 FileSystemWatcher의 스레드에서 이벤트를 펄스하는 경우에도 매우 적습니다. 그래서 버퍼를 최대로 설정하는 것이 잘못이라고 생각하지 않습니다. – fpdragon