2016-07-07 5 views
3

Ich erstelle einen Scheduler, um Ereignisse zu bestimmten Tageszeiten auszulösen, und dazu spanne ich Aufgaben (einzeln, dh nur den nächsten) mit einer Task.Delay von allem nach oben zu ein paar Tagen Verspätung. Zum Beispiel, nachdem das letzte Ereignis an einem Freitagnachmittag ausgelöst wurde, richte ich das nächste Ereignis ein, das am Montag stattfinden wird. Es könnte also ein TimeSpan von bis zu 3 Tagen sein (~ 260.000.000 Millisekunden).Ist es akzeptabel, Aufgaben mit langen Verzögerungen zu erstellen?

Ist das akzeptabel? Ich bin besorgt, dass dies für eine Produktionsumgebung nicht stabil genug sein wird.

Hier einige Code-Schnipsel zu beschreiben, was ich habe zusammen:

private void SetNextEvent() 
{ 
    TimeModel next = GetNextScheduledTime(); 
    Debug.WriteLine($"Next schedule [{next.TimeType}]: {next.Time.ToString("yyyy-MM-dd HH:mm:ss")}"); 

    TimeSpan delay = next.Time.Subtract(DateTime.Now); 
    Task.Run(async() => 
    { 
     await Task.Delay(delay); 
     FireEvent(next); 
    }); 
} 

private void FireEvent(TimeModel time) 
{ 
    Debug.WriteLine($"Event fired [{time.TimeType}]: {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); 
    OnSchedulerEvent?.Invoke(this, new SchedulerEventArgs { ScheduleType = time.TimeType }); 
    if (_running) 
     SetNextEvent(); 
} 
+4

Kann es funktionieren? Ich nehme an. Der erste Gedanke ist, dass wenn der Server neu gestartet werden muss, Sie ohne dauerhaften Zustand abgespritzt werden. Es gibt viele Scheduler wie [Quartz] (http://www.quartz-scheduler.net/), die speziell dafür entwickelt wurden. Ich denke, dass sie eine stärkere Entscheidung wären. –

+0

Wenn der Server neu gestartet wird, wird der Dienst neu gestartet, es wird SetNextEvent aufgerufen, das dieselbe nächste geplante Zeit zurückgibt, und eine Aufgabe mit einem TimeSpan von diesem Punkt aus ... Ich habe Quartz in Betracht gezogen, aber für was ich kann in diesen beiden Methoden erreichen, schien es ein bisschen übertrieben. – Detail

+1

Sie sollten nach einer negativen 'TimeSpan-Verzögerung 'suchen, vorausgesetzt, das Verhalten von' GetNextScheduledTime' bleibt gleich, bis FireEvent erfolgreich ausgeführt wird. Da kann es zu einem Problem kommen, dass die Uhr die nächste geplante Zeit überschreitet, während der Server neu gestartet wird. Schlimmer noch, es schaffte es, genau -1 Millisekunden zu erreichen, "Task.Delay" endet nie. – ShuberFu

Antwort

3

Dies ist absolut zuverlässig. .NET-Timer sind sehr effizient. Das größte Problem ist, dass Sie davon ausgehen müssen, dass Ihre Produktions-Apps jederzeit beendet werden können. Der am leichtesten zu verstehende Grund ist ein Fehler, der den Prozess umbringt. Andere Gründe sind Neustarts, App Pool Rezyklierungen, Bereitstellungen, ...

Also, wenn Sie Ihren Zustand wiederherstellen können, nachdem getötet wurde, ist das in Ordnung. Wenn Sie einen Kommentar zu bestimmten Bedenken hinzufügen, werde ich sie ansprechen.

Es sieht so aus, als ob Sie eine Möglichkeit haben, Timer wiederherzustellen, weil Sie scheinbar die nächste fällige Zeit berechnen können. Unter diesen Umständen ist es sehr sicher, dies zu tun. Sie müssen sicherstellen, dass Ihr Code immer z. direkt nach einem Neustart oder einem Absturz.

Beachten Sie, dass IIS-Anwendungen mehrere Male gleichzeitig ausgeführt werden müssen. Ansonsten ist IIS ein großartiger Host für Ihr Szenario.

+1

Hallo, danke, genau das habe ich gesucht. Ich kann den Status leicht wiederherstellen, und ich habe Code, der verpasste Zeitpläne erkennt und sie "spät" wiederholt, solange sie nicht abgeschnitten haben. Verpasste Zeitpläne sind eigentlich in Ordnung, natürlich nicht auf Dauer, aber One-Offs sind kein Problem. Mein Hauptanliegen war, dass der Thread, der auf die Verzögerung wartet, austritt oder "veraltet" wurde oder dass die Dauer (Tage) einen Fehler verursachte oder aus irgendeinem Grund nicht ratsam war. – Detail

+0

Gute Frage, aber das ist kein Problem. – usr

0

Wenn Sie Windows ausführen, würde ich den Taskscheduler verwenden zu tun, was Sie versuchen zu tun.

ausführen taskschd.msc Sie können dieses Programm verwenden, um periodische Aufgaben zu planen.

Es sollte eine Schaltfläche "Create Task ..." im Panel auf der rechten Seite sein.

+0

Es ist eine andere Art von "Task". tasschd.msc plant Befehlszeilen- und ausführbare Tasks. Die parallele Task-Bibliothek ist für * aufrufbare * Tasks wie Funktionen, Methoden, Subroutinen etc. – RBarryYoung

+0

Genau, plus die Verwendung des Windows-Schedulers würde bedeuten, dass ich (oder vielmehr jemand anders) von Hand Tausende von Zeitplänen von Hand konfigurieren müsste Für immer mehr – Detail

+0

@RBarryYoung Es ist nicht so anders. Sie benötigen jeden Tag Code, den der Taskplaner ausführen kann. Selbst wenn Sie Ihre App speziell dazu benötigen, etwas zu tun, zB den Speicherzustand ändern, können Sie den Taskplaner weiterhin verwenden, um einen WebApi-Endpunkt in Ihrer ursprünglichen App auszulösen. –

0

Ich stimme zu, dass der Windows Taskplaner wahrscheinlich der beste Ansatz ist, wenn Sie im Voraus den Zeitplan für die Ausführung der nächsten Aufgabe kennen.

Wenn Sie dies nicht im Voraus wissen (d. H. Die Wartezeit für die nächste Aufgabe kann variieren), würde ich vorschlagen, einen Timer und eine Event-Handler-Methode zu verwenden, wenn der Timer abläuft.

Jedes Mal können Sie die Intervall-Eigenschaft des Timers für die Wartezeit einstellen. Wenn die Zeit abläuft, wird der Timer-Ereignishandler ausgeführt, und er kann die Abfrage ausführen und das Intervall für den Timer zurücksetzen. Dies scheint ein wenig sauberer als eine Task.Delay.

+0

Gibt es etwas, das eine bessere Lösung rechtfertigen könnte? Ich habe darüber nachgedacht und eine Lösung mit Timers implementiert, aber für mich schien der asynchrone Warteansatz sauberer zu sein und ist ein Muster, das ich gerne im Team fördern würde. Unter der Decke fragte ich mich, ob sie beide relativ gleich sind ... – Detail

+0

Die Task.Delay startet einen Timer im Hintergrund. Die Verarbeitung ist für den Ressourcenverbrauch und das Entsperren von Threads identisch. Ich bin nicht sicher, ob ich das Wort "besser" verwenden würde, um beide Ansätze zu beschreiben. –