Ich habe eine Methode in der ASP.NET-Anwendung, deren Fertigstellung ziemlich viel Zeit in Anspruch nimmt. Ein Aufruf dieser Methode kann je nach Cache-Status und vom Benutzer angegebenen Parametern bis zu dreimal während einer Benutzeranforderung erfolgen. Jeder Anruf dauert ca. 1-2 Sekunden. Die Methode selbst ist ein synchroner Aufruf des Dienstes und es gibt keine Möglichkeit, die Implementierung zu überschreiben.
Der synchrone Aufruf des Dienstes sieht also ungefähr so aus:
public OutputModel Calculate(InputModel input)
{
// do some stuff
return Service.LongRunningCall(input);
}
Und die Verwendung der Methode ist (beachten Sie, dass der Aufruf der Methode mehr als einmal vorkommen kann):
private void MakeRequest()
{
// a lot of other stuff: preparing requests, sending/processing other requests, etc.
var myOutput = Calculate(myInput);
// stuff again
}
Ich habe versucht, die Implementierung von meiner Seite zu ändern, um die gleichzeitige Arbeit mit dieser Methode zu ermöglichen, und hier ist, worauf ich bisher gekommen bin.
public async Task<OutputModel> CalculateAsync(InputModel input)
{
return await Task.Run(() =>
{
return Calculate(input);
});
}
Verwendung (ein Teil des Codes "Andere Dinge erledigen" wird gleichzeitig mit dem Aufruf des Dienstes ausgeführt):
private async Task MakeRequest()
{
// do some stuff
var task = CalculateAsync(myInput);
// do other stuff
var myOutput = await task;
// some more stuff
}
Meine Frage lautet wie folgt. Benutze ich den richtigen Ansatz, um die Ausführung in der ASP.NET-Anwendung zu beschleunigen, oder mache ich unnötige Arbeit, um synchronen Code asynchron auszuführen? Kann jemand erklären, warum der zweite Ansatz in ASP.NET keine Option ist (wenn dies wirklich nicht der Fall ist)? Wenn ein solcher Ansatz anwendbar ist, muss ich eine solche Methode asynchron aufrufen, wenn dies der einzige Aufruf ist, den wir derzeit ausführen können (ich habe einen solchen Fall, in dem keine anderen Aufgaben zu erledigen sind, während auf den Abschluss gewartet wird)?
Die meisten Artikel im Internet zu diesem Thema behandeln die Verwendung des async-await
Ansatzes mit dem Code, der bereits awaitable
Methoden bereitstellt , aber das ist nicht mein Fall. Hierist der schöne Artikel, der meinen Fall beschreibt, der die Situation von parallelen Anrufen nicht beschreibt und die Option zum Umbrechen von Synchronisierungsanrufen ablehnt, aber meiner Meinung nach ist meine Situation genau die Gelegenheit, dies zu tun.
Vielen Dank im Voraus für Hilfe und Tipps.
quelle
Task.Run
, wird der Inhalt in einem anderen Thread ausgeführt, der aus dem Thread-Pool stammt. Dann besteht überhaupt keine Notwendigkeit, blockierende Aufrufe (wie z. B. meinen Aufruf zum Dienst) inRun
s zu verpacken , da sie immer jeweils einen Thread verbrauchen, der während der Ausführung der Methode blockiert wird. In einer solchen Situation besteht der einzige Vorteil, derasync-await
in meinem Fall übrig bleibt, darin, mehrere Aktionen gleichzeitig auszuführen. Bitte korrigiere mich wenn ich falsch liege.Run
(oderParallel
) erhalten, ist die Parallelität. Die Operationen blockieren immer noch jeweils einen Thread. Da Sie sagen, dass der Dienst ein Webdienst ist, empfehle ich nicht,Run
oder zu verwendenParallel
. Schreiben Sie stattdessen eine asynchrone API für den Dienst.BeginGetResponse
und mehrere davon starten und dann (synchron) blockieren, bis alle vollständig sind. Diese Vorgehensweise ist jedoch schwierig - siehe blog.stephencleary.com/2012/07/dont-block-on -async-code.html und msdn.microsoft.com/en-us/magazine/mt238404.aspx .async
Wenn möglich, ist es normalerweise einfacher und sauberer, den gesamten Weg zu übernehmen .Ich habe festgestellt, dass der folgende Code eine Aufgabe so konvertieren kann, dass sie immer asynchron ausgeführt wird
und ich habe es auf folgende Weise verwendet
Dadurch wird jede Aufgabe asynchron ausgeführt, sodass Sie sie in WhenAll-, WhenAny-Szenarien und anderen Verwendungszwecken kombinieren können.
Sie können auch einfach Task.Yield () als erste Zeile Ihres aufgerufenen Codes hinzufügen.
quelle