2017-09-22 1 views
0

Ich habe einen Prozess, wo ich FileSystemWatcher spin up, um das Dateisystem für eingehende Dateien zu sehen.Wie füge ich einer verzögerten Aufgabe Zeit hinzu?

Ich habe eine Verzögerung mit Task.Delay eingerichtet, die den FSW abbricht, entweder wenn das Stornierungs-Token gesetzt ist oder nach Ablauf der Zeit (zum Beispiel 10 Minuten).

Aber ich würde es gerne so konfigurieren, dass ich jedes Mal, wenn eine neue Datei erscheint, zusätzliche Verzögerung hinzufügen kann. Also effektiv eine Art gleitende Ablaufverzögerung.

+3

abbrechen und neu erstellen? – Default

+0

Das war anfangs mein Gedanke, aber ich würde gerne den FSW laufen lassen, wenn es möglich wäre, weil es Dateien geben könnte, die alle paar Sekunden (oder weniger) eintreffen und dies würde zu vielen Stornierungen und Wiederholungen führen. Was ich im Wesentlichen erreichen möchte ist, dass der FSW läuft, seit die erste Datei kommt und bis die letzten Dateien + 10 Minuten sind. – mare

+0

Nein, sorry, abbrechen und den _running task_ neu erstellen. also ein 'restartTimeoutCancellation' abbrechen .. lass mich sehen ob ich es in einen verständlichen satz formulieren kann :) – Default

Antwort

2

Sie könnten Ihre Verzögerungsmethode leicht ändern, um die Ausführungszeit verschieben zu können.

Ich habe ein kleines Beispiel für Sie erstellt.

Anschließend können Sie machen nur eine "verzögerte dispose" des FileSystemWatcher auf einfache Weise:

CancellationTokenSource cts = new CancellationTokenSource(); 
await watcher.DisposeDelayed(TimeSpan.FromSeconds(10), cts.Token); 

Ich habe eine Erweiterungsmethode für die FileSystemWatcher:

static class Utilities 
{ 
    public static async Task DisposeDelayed(this FileSystemWatcher watcher, TimeSpan inactivePeriod, CancellationToken ct) 
    { 
     DateTime disposalTime = DateTime.Now + inactivePeriod; 
     FileSystemEventHandler postponeTrigger = (s, e) => disposalTime = DateTime.Now + inactivePeriod; 
     watcher.Created += postponeTrigger; 
     watcher.Changed += postponeTrigger; 
     // add here other event handlers you need to postpone the disposal 

     try 
     { 
      await RunAtTimePoint(() => disposalTime, ct, watcher.Dispose).ConfigureAwait(false); 
     } 
     finally 
     { 
      // don't forget to unsubscribe from each event 
      watcher.Created -= postponeTrigger; 
      watcher.Changed -= postponeTrigger; 
     } 
    } 

    // You can also use this method for other tasks if you need 
    public static async Task RunAtTimePoint(Func<DateTime> execTimeProvider, CancellationToken token, Action action) 
    { 
     int delayTime; 
     do 
     { 
      // first, calculate the time left until the execution 
      DateTime execTime = execTimeProvider(); 
      TimeSpan timeLeft = execTime - DateTime.Now; 

      // we delay in 1000 ms chunks; 
      // but if the delay time is less, we need to handle that 
      delayTime = (int)Math.Min(1000d, timeLeft.TotalMilliseconds); 
      if (delayTime > 0) 
      { 
       // don't forget the ConfigureAwait call: 
       // we don't need the context switch each time 
       await Task.Delay(delayTime, token).ConfigureAwait(false); 
      } 
     } 
     while (delayTime > 0 && !token.IsCancellationRequested); 

     if (!token.IsCancellationRequested) 
     { 
      action(); 
     } 
    } 
} 
+0

Ich habe noch Gedanken daran, mit diesem Code zu gehen, sieht ziemlich kompliziert aus. – mare

Verwandte Themen