2010-02-09 4 views
10

파일을 수정할 때 이벤트를 트리거하는 filesystemwatcher가 있습니다. 자물쇠가 제거되면 그 파일을 읽고 싶습니다. 큰 파일을 복사 할 때 이벤트가 전송 된 후 잠시 동안 파일 잠금이 유지되면서 파일이 읽기 액세스를 위해 열리지 않도록하면서 이벤트가 트리거되면이 파일을 열려고합니다.파일 스트림 열기를위한 FileSystemWatcher 트리거

제안 사항?

답변

6

내가 마지막으로 문제를 처리 한 이후로 문제 공간이 크게 변경되지 않는 한이 프로그램은 실제로 약간의 doozie입니다.

가장 쉬운 방법은 파일을 열어 결과로 나타나는 IOException을 잡는 것입니다. 파일이 잠겨 있으면 나중에 확인할 대기열에 파일을 추가하십시오. 동일한 파일에 대해 여러 개의 이벤트가 생성되는 모든 종류의 경우가 있기 때문에 들어오는 모든 파일을 처리 할 수는 없으므로 수신 된 모든 이벤트에 대해 재시도 루프를 설정하면 재앙이 될 수 있습니다. 대신 대기열에 넣고 일정한 간격으로 대기열을 확인해야합니다. 여기

이 문제에 당신을 도울해야 기본 클래스 템플릿입니다 :

public class FileMonitor : IDisposable 
{ 
    private const int PollInterval = 5000; 

    private FileSystemWatcher watcher; 
    private HashSet<string> filesToProcess = new HashSet<string>(); 
    private Timer fileTimer; // System.Threading.Timer 

    public FileMonitor(string path) 
    { 
     if (path == null) 
      throw new ArgumentNullException("path"); 

     watcher = new FileSystemWatcher(); 
     watcher.Path = path; 
     watcher.NotifyFilter = NotifyFilters.FileName; 
     watcher.Created += new FileSystemEventHandler(FileCreated); 
     watcher.EnableRaisingEvents = true; 

     fileTimer = new Timer(new TimerCallback(ProcessFilesTimer), 
      null, PollInterval, Timeout.Infinite); 
    } 

    public void Dispose() 
    { 
     fileTimer.Dispose(); 
     watcher.Dispose(); 
    } 

    private void FileCreated(object source, FileSystemEventArgs e) 
    { 
     lock (filesToProcess) 
     { 
      filesToProcess.Add(e.FullPath); 
     } 
    } 

    private void ProcessFile(FileStream fs) 
    { 
     // Your code here... 
    } 

    private void ProcessFilesTimer(object state) 
    { 
     string[] currentFiles; 
     lock (filesToProcess) 
     { 
      currentFiles = filesToProcess.ToArray(); 
     } 
     foreach (string fileName in currentFiles) 
     { 
      TryProcessFile(fileName); 
     } 
     fileTimer.Change(PollInterval, Timeout.Infinite); 
    } 

    private void TryProcessFile(string fileName) 
    { 
     FileStream fs = null; 
     try 
     { 
      FileInfo fi = new FileInfo(fileName); 
      fs = fi.OpenRead(); 
     } 
     catch (IOException) 
     { 
      // Possibly log this error 
      return; 
     } 

     using (fs) 
     { 
      ProcessFile(fs); 
     } 

     lock (filesToProcess) 
     { 
      filesToProcess.Remove(fileName); 
     } 
    } 
} 

(주 - 버그가 있다면 알려주세요 - 완벽하지 않을 수도 있습니다, 그래서 내가 여기에 메모리에서이 리콜 해요 .)

+0

니스, 내가 기다리고있는 동안 같이 갔다. 나는 타임 아웃과 재시도 대기를 사용했다. 나는 좀 더 우아하고 좋은 것을 원했었다.) (대단한 답변을 얻으려는 노력에 대한 백만의 감사) – Matthew