2017-11-17 5 views
0

Wir sind vor kurzem zu einem CSVFS Clustered File Server gegangen. Ich habe einen Beobachter-Datei, die 4-Verzeichnisse für OnCreated und OnRenamed Eventss Überwachung aber immer dann, wenn der Knoten ändert, ist es einen Pufferüberlauf mit dem FehlerDer beste Weg, um wechselnde Knoten zu behandeln? - C# File Watcher und Clustered File Server

Zu viele Änderungen auf einmal

im Verzeichnis bewirkt, dass die die Beobachter werden automatisch neu gestartet und der Prozess läuft weiter, aber beginnt Fehler zu schreiben, wenn die OnCreated/OnRenamed Ereignisse ausgelöst werden.

Zugriff auf ein entsorgtes Objekt nicht möglich.
Objektname: 'FileSystemWatcher'.
bei System.IO.FileSystemWatcher.StartRaisingEvents()
bei System.IO.FileSystemWatcher.set_EnableRaisingEvents (Boolean Wert)

Im OnCreated Methode unten, wenn ich dies zu tun war, sollte es funktionieren?

watchit = source as FileSystemWatcher; 

ich eigentlich gar nicht vergeben die neu geschaffene FileSystemWatcher-watchit anderswo.

Weitere Details/code

Die Beobachter werden über eine foreach-Schleife erstellt, wenn der Prozess zunächst beginnt. FileChange ist einfach eine Methode, die die Art der Änderung bestimmt, ein wenig Arbeit leistet und dann die richtige Aktion für den Änderungstyp auslöst.

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 ist eine statische FileSystemWatcher global festgelegt.

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; 
} 

Dies sind meine Fehlerbehandlungsmethoden.

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) { } 
     } 

Antwort

0

Sie versuchen, zu viel Arbeit in den FileSystemWatcher Ereignissen zu tun. Die Beobachter werden von nicht verwalteten Puffern unterstützt, die so schnell wie möglich geleert werden müssen, um mit den Änderungen Schritt zu halten.

Im Idealfall sollten alle Ereignisse nur sehr grundlegende Daten wie den geänderten Pfad und die Art der Änderung lesen und diese in die Warteschlange einreihen, damit sie in einem anderen Thread verarbeitet werden können. Dieser andere Thread kann das schwere Heben durchführen, da er den nicht verwalteten Änderungspuffer nicht blockiert.

Verwandte Themen