2017-11-17 3 views
0

最近、CSVFSクラスタ化ファイルサーバーに行きました。 I OnCreatedOnRenamedイベントのために4ディレクトリを監視していますファイルウォッチャーを持っていますが、いつでもノードの変更、それはバッファオーバーフローが発生するエラーと変更するノードを処理する最も良い方法は? - C#File WatcherとClustered File Server

ディレクトリに一度にあまりにも多くの変化

ウォッチャー自動的に再起動され、プロセスは動作し続けますが、OnCreated/OnRenamedイベントが発生するとエラーの書き込みが開始されます。

配置されたオブジェクトにアクセスできません。
オブジェクト名: 'FileSystemWatcher'。以下OnCreated方法で
System.IO.FileSystemWatcher.StartRaisingEventsで System.IO.FileSystemWatcher.set_EnableRaisingEventsで()
(ブール値)

私はこれを行うにした場合、それが動作するはず?

watchit = source as FileSystemWatcher; 

私は実際にはどこにもwatchitに新しく作成されたFileSystemWatcherを割り当てないでください。

詳細/コード

プロセスが最初に開始するときウォッチャーは、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イベントであまりにも多くの作業を実行しようとしています。ウォッチャーは、変更に追いつくためにできるだけ早く空にする必要がある管理されていないバッファーによってバックアップされます。

理想的には、変更されたパスや変更のタイプなどの非常に基本的なデータを読んで、それを別のスレッドで処理するためにキューに投げ込むことです。他のスレッドは、アンマネージ変更バッファをブロックしないので、重い作業を行うことができます。

関連する問題