2017-11-17 18 views
0

최근에 CSVFS 클러스터 파일 서버를 방문했습니다. 나는 노드 변경, 그것은변경하는 노드를 처리하는 가장 좋은 방법은 무엇입니까? - C# File Watcher 및 Clustered File Server

너무 많은 변화를 한 번 디렉토리에

다음은 전문가에 오류가있는 버퍼 오버 플로우가 발생 할 때마다 파일 OnCreatedOnRenamed 이벤트를 4 디렉토리를 모니터링하는 것 감시자하지만이 가 자동으로 다시 시작되고 프로세스는 계속 작동하지만 OnCreated/OnRenamed 이벤트가 발생하면 오류 쓰기가 시작됩니다.

폐기 된 개체에 액세스 할 수 없습니다.
개체 이름 : 'FileSystemWatcher'. 나는이 작업을 수행 할 수 있다면 System.IO.FileSystemWatcher.StartRaisingEvents에서
() System.IO.FileSystemWatcher.set_EnableRaisingEvents에서
(부울 값) 아래 OnCreated 방법에서

, 그것은 작동 하는가?

watchit = source as FileSystemWatcher; 

는 사실은 다른 곳에서는 새로 만든 FileSystemWatcherwatchit 할당하지 않습니다.

더 많은 정보/코드

프로세스가 처음 시작될 때 관찰자가 foreach 루프를 통해 생성된다. FileChange은 단순히 변경 유형을 결정하고 약간의 작업을 수행 한 다음 변경 유형에 대한 올바른 작업을 트리거하는 메소드입니다.

foreach (string subDir in subDirs) 
{ 
    string localFolder = $"{subDir}"; 

    watchit = new FileSystemWatcher 
        { 
         Path = localFolder, 
         EnableRaisingEvents = true, 
         IncludeSubdirectories = false, 
         NotifyFilter = NotifyFilters.FileName | NotifyFilters.CreationTime, 
         Filter = watchFor, 
         InternalBufferSize = 65536, 
         SynchronizingObject = null //, 
        }; 

    watchit.Changed += FileChange; 
    watchit.Created += FileChange; 
    watchit.Deleted += FileChange; 
    watchit.Renamed += OnRename; 
    watchit.Error += OnError; 
    watchit.EnableRaisingEvents = true; 

    watchers.Add(watchit); 

    Console.WriteLine($"watching {subDir} for {watchFor}"); 
} 

watchit 전역 설정된 정적 FileSystemWatcher이다.

private static async Task<int> OnCreated<T>(object source, FileSystemEventArgs e, string ext) 
{ 
    int insertResult = 0; 

    try 
    { 
     watchit.EnableRaisingEvents = false; 
     EventLogWriter.WriteEntry("File: " + e.FullPath + " " + e.ChangeType); 
     Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType + " " + DateTime.Now); 
     insertResult = await FileHandler.FileHandlers().ConfigureAwait(false); 
     watchit.EnableRaisingEvents = true; 
     // if (insertResult > 0) File.Delete(e.FullPath); 
    } 
    catch (Exception ex) 
    { 
     Logger.Trace($"{ex.Message} {ex.StackTrace} {ex.InnerException}"); 
     EventLogWriter.WriteEntry($"{ex.Message} {ex.StackTrace} {ex.InnerException}", 
     EventLogEntryType.Error); 
     watchit.EnableRaisingEvents = true; 
    } 
    finally 
    { 
     watchit.EnableRaisingEvents = true; 
    } 

    return insertResult; 
} 

이들은 나의 오류 처리 방법입니다.

private static void OnError(object source, ErrorEventArgs e) 
{ 
    if (e.GetException().GetType() == typeof(InternalBufferOverflowException)) 
    { 
     EventLogWriter.WriteEntry($"Error: File System Watcher internal buffer overflow at {DateTime.Now}", EventLogEntryType.Warning); 
    } 
    else 
    { 
     EventLogWriter.WriteEntry($"Error: Watched directory not accessible at {DateTime.Now}", EventLogEntryType.Warning); 
    } 

    MailSend.SendUploadEmail($"ASSIST NOTES: {e.GetException().Message}", "The notes service had a failure and should be restarted.", "admins", e.GetException(), MailPriority.High); 
    NotAccessibleError(source as FileSystemWatcher, e); 
} 

    /// <summary> 
    /// triggered on accessible error. 
    /// </summary> 
    /// <param name="source">The source.</param> 
    /// <param name="e">The <see cref="ErrorEventArgs"/> instance containing the event data.</param> 
    private static void NotAccessibleError(FileSystemWatcher source, ErrorEventArgs e) 
     { 
     EventLogWriter.WriteEntry($"Not Accessible issue. {e.GetException().Message}" + DateTime.Now.ToString("HH:mm:ss")); 

     int iMaxAttempts = 120; 
     int iTimeOut = 30000; 
     int i = 0; 
     string watchPath = source.Path; 
     string watchFilter = source.Filter; 
     int dirExists = 0; 
     try 
      { 
      dirExists = Directory.GetFiles(watchPath).Length; 
      } 
     catch (Exception) { } 
     try 
      { 
      while (dirExists == 0 && i < iMaxAttempts) 
       { 
       i += 1; 
       try 
        { 
        source.EnableRaisingEvents = false; 
        if (!Directory.Exists(source.Path)) 
         { 
         EventLogWriter.WriteEntry(
          "Directory Inaccessible " + source.Path + " at " + 
          DateTime.Now.ToString("HH:mm:ss")); 
         Console.WriteLine(
          "Directory Inaccessible " + source.Path + " at " + 
          DateTime.Now.ToString("HH:mm:ss")); 
         System.Threading.Thread.Sleep(iTimeOut); 
         } 
        else 
         { 
         // ReInitialize the Component 
         source.Dispose(); 
         source = null; 
         source = new System.IO.FileSystemWatcher(); 
         ((System.ComponentModel.ISupportInitialize)(source)).BeginInit(); 
         source.EnableRaisingEvents = true; 
         source.Filter = watchFilter; 
         source.Path = watchPath; 
         source.NotifyFilter = NotifyFilters.FileName | NotifyFilters.CreationTime; 
         source.Created += FileChange; 
         source.Renamed += OnRename; 
         source.Error += new ErrorEventHandler(OnError); 
         ((System.ComponentModel.ISupportInitialize)(source)).EndInit(); 
         EventLogWriter.WriteEntry(
          $"Restarting watcher {watchPath} at " + DateTime.Now.ToString("HH:mm:ss")); 
         dirExists = 1; 
         } 
        } 
       catch (Exception error) 
        { 
        EventLogWriter.WriteEntry($"Error trying Restart Service {watchPath} " + error.StackTrace + 
               " at " + DateTime.Now.ToString("HH:mm:ss")); 
        source.EnableRaisingEvents = false; 
        System.Threading.Thread.Sleep(iTimeOut); 
        } 
       } 
      //Starts a new version of this console appp if retries exceeded 
      //Exits current process 
      var runTime = DateTime.UtcNow - Process.GetCurrentProcess().StartTime.ToUniversalTime(); 
      if (i >= 120 && runTime > TimeSpan.Parse("0:00:30")) 
       { 
       Process.Start(Assembly.GetExecutingAssembly().Location); 
       Environment.Exit(666); 
       } 
      } 
     catch (Exception erw) { } 
     } 

답변

0

FileSystemWatcher 이벤트에서 너무 많은 작업을 수행하려고합니다. 감시자는 관리되지 않는 버퍼에 의해 백업되므로 변경 사항을 따라 잡기 위해 가능한 한 빨리 비워야합니다.

이상하게도, 모든 이벤트는 변경된 경로와 같은 매우 기본적인 데이터를 읽는 것이고, 변경 유형과이를 다른 스레드에서 처리하기 위해 대기열에 던지기위한 것입니다. 다른 스레드는 관리되지 않는 변경 버퍼를 차단하지 않으므로 과도한 작업을 수행 할 수 있습니다.