Ich arbeite an einem Web-API-Projekt, das den verwalteten Cache-Dienst von Azure zum Zwischenspeichern von Datenbankergebnissen im Speicher verwendet, um Antwortzeiten zu verbessern und doppelten Datenverkehr zur Datenbank zu verringern. Beim Versuch, ein neues Objekt in den Cache zu stellen, wird gelegentlich eine cache-spezifische Ausnahme mit dem Code DataCacheErrorCode.RetryLater
ausgelöst. Natürlich, um später erneut zu versuchen, ohne auf diese Methode zu blockieren, habe ich es async
und await Task.Delay
gemacht, um es kurze Zeit später erneut zu versuchen. Zuvor hatte ein Entwickler eine Thread.Sleep
darin hartcoded, die wirklich Anwendungsleistung schädigte.Überlegungen zum Warten auf einen Task in einer asynchronen Methode
Die Signatur der Methode sieht nun dazu etwas ähnliches:
public static async Task Put(string cacheKey, object obj)
Nach dieser Änderung, die ich bekomme ~ 75 Compiler-Warnungen von allen anderen Orten in der Anwendung, die die ehemals synchrone Version von Put
angibt, genannt:
Da dieser Aufruf nicht erwartet wird, wird die Ausführung der aktuellen Methode fortgesetzt, bevor der Aufruf abgeschlossen wird. Erwägen Sie, den Operator 'abwarten' auf das Ergebnis des Aufrufs anzuwenden.
In diesem Fall, da Put
nichts zurückliefert, macht es Sinn für mich diese Operation fire-and-forget wie ich aus irgendeinem Grund Durchführung des Verfahrens blockieren nicht sehen zu lassen, die aufgerufen es. Ich frage mich nur, ob es irgendwelche Gefahren oder Fallstricke für das Erlauben einer Menge dieser Feuer-und-vergessen Task
s gibt, die im Hintergrund laufen, da Put
ziemlich häufig genannt werden kann. Oder sollte ich sowieso warten, da ich 99% der Zeit nicht den Wiederholungsfehler bekomme und die Task
wird fast sofort fertig. Ich möchte nur sicherstellen, dass ich keine Strafen für zu viele Threads (oder so ähnlich) bekomme.
Danke für das gute Feedback. Derzeit werden alle Ausnahmen außer RetryLater abgefangen und ordnungsgemäß protokolliert, und wir befinden uns in .NET 4.5, so dass ich zuversichtlich bin, diese Aufgaben zu aktivieren und zu vergessen. –
Technisch Timer verwendet einen [separaten] Thread aus einem Thread-Pool, also Task.Delay() – alexm
@alexm Es verwendet einen Thread-Pool-Thread für eine sehr kurze Zeit nach Ablauf der Zeit, um den Handler auszuführen. Es wird kein Thread-Thread während des Wartens konsumiert. Dies bedeutet, dass ein Thread nur dann verwendet wird, wenn er produktive Arbeit hat, die genau das ist, was Sie wollen (und nicht vermeiden können). – Servy