2016-10-05 3 views
0

Statt manuell mit einem DispatcherTimer Hantieren Ich kam auf diese:while (true) + Task.Delay() innerhalb der asynchronen Void-Methode; sollte ich Schwierigkeiten erwarten?

public async void StartWatching() 
    { 
     Debug.Assert(SynchronizationContext.Current is DispatcherSynchronizationContext, "SynchronizationContext.Current is DispatcherSynchronizationContext"); 
     while (true) 
     { 
      this.GC0 = GC.CollectionCount(0); 
      this.GC1 = GC.CollectionCount(1); 
      this.GC2 = GC.CollectionCount(2); 
      this.RAM = GC.GetTotalMemory(false); 
      await Task.Delay(1500); 
     } 
    } 

Dieser Code nicht über Garbage Collection ist, sondern nur zeigen Statistiken über eine Statusleiste angezeigt.

Dies wird einmal gestartet (von innerhalb Application.OnStartup) und soll für die gesamte Laufzeit der Anwendung ausgeführt werden.

Einzel Frage

Wird mir dies in jede Art von Schwierigkeiten geraten, wenn langfristige (Wochen) läuft?

+0

Warum * müssen * Sie die Garbage Collection manuell initiieren? –

+0

@MikeEason Ich zeige nur Statistiken über eine Statusleiste. – springy76

+0

Wo ist das Problem mit einem Timer? Dies ist der Anwendungsfall für Timer, warum brauchen Sie eine Alternative? – JeffRSon

Antwort

1

Ich persönlich glaube nicht, dass es etwas besonders Schlechtes an dieser Methode gibt, verglichen mit der Verwendung von DispatcherTimer. Ich persönlich habe auch diese Methode benutzt - sie ist sehr kurz und direkt auf den Punkt gebracht.

Beachten Sie jedoch, dass async Methoden Ihre Anwendung nicht zum Absturz bringen - sie sterben lautlos, ohne dass Sie es wissen. Daher müssen Sie alle möglichen Ausnahmen einfangen, die Ihnen einfallen. Auch alle finally Blöcke innerhalb async Methoden würden nicht so gut laufen. Sie sollten auch darüber nachdenken, CancellationToken hinzuzufügen.

Für Ihren Fall, sehe ich nicht, dass das Problem verursachen würde.

+1

Ich kann das nicht bestätigen: Exceptions, die vor oder nach 'erwarten' geworfen werden, kommen glücklicherweise zum' Application.DispatcherUnhandledException' Event. Ist das nicht die Spezialität über Async VOID? – springy76

2

Wird mir das bei langen Laufzeiten (Wochen) Probleme bereiten?

Nicht wirklich. Es gibt jedoch einige Dinge zu beachten.

Da Ihre Methode async void zurückgibt, werden alle Ausnahmen direkt auf der SynchronizationContext ausgelöst, die zu Beginn der Methode aktuell war. Also, sie werden direkt zum Dispatcher (oder Anwendung für WinForms) gehen. Es hört sich so an, als ob dieses Verhalten sein könnte.

Die Ausführung von Arbeit gefolgt von einer Verzögerung unterscheidet sich von der Verwendung eines periodischen Timers, insbesondere wenn die Arbeit unterschiedlich lange dauern kann. Dieser Code wird also nicht alle 1,5 Sekunden ausgeführt. Es wird ein bisschen seltener sein. Der Vorteil von es auf diese Weise ist, dass Sie nicht über überlappenden Code sorgen müssen, wie Sie mit einem rein periodischen Timer tun.

Es wird auch mehr "Jitter" geben. Was passiert unter den Abdeckungen ist, dass Task.Delay startet einen Thread-Pool Timer, und wenn das ausgelöst wird, dann wird es die Aufgabe abschließen; An diesem Punkt ist die Fortsetzung für StartWatchinggeplant für den UI-Thread, und es wird geduldig warten, bis der UI-Thread frei sein, bevor Sie seine Arbeit ausführen. Es wird also ein zusätzliches "Warten auf den UIhread" geben, das eine variable Zeitspanne benötigt - normalerweise sofort, aber manchmal warten alle Ihre UI-Bindungen, um zu aktualisieren, ...

Schließlich können sehr kleine Verzögerungen auftreten funktioniert nicht gut. Die WinForm- und Dispatcher-Timer verwenden erweiterte Mechanismen (die direkt in die Nachrichtenschleifen integriert sind), um eine höhere Genauigkeit zu erzielen. Aufgrund des zusätzlichen Overheads von Task.Delay glaube ich, dass es in einer echten App nicht für sehr kleine Verzögerungen funktionieren wird. (Dies ist nur ein Bauchgefühl, nicht das Ergebnis der Tests).

Verwandte Themen