Ich habe die folgende Operation in einer von mir erstellten Web-API:
// GET api/<controller>
[HttpGet]
[Route("pharmacies/{pharmacyId}/page/{page}/{filter?}")]
public CartTotalsDTO GetProductsWithHistory(Guid pharmacyId, int page, string filter = null ,[FromUri] bool refresh = false)
{
return delegateHelper.GetProductsWithHistory(CustomerContext.Current.GetContactById(pharmacyId), refresh);
}
Der Aufruf dieses Webservices erfolgt über einen Jquery Ajax-Aufruf auf folgende Weise:
$.ajax({
url: "/api/products/pharmacies/<%# Farmacia.PrimaryKeyId.Value.ToString() %>/page/" + vm.currentPage() + "/" + filter,
type: "GET",
dataType: "json",
success: function (result) {
vm.items([]);
var data = result.Products;
vm.totalUnits(result.TotalUnits);
}
});
Ich habe einige Entwickler gesehen, die die vorherige Operation folgendermaßen implementieren:
// GET api/<controller>
[HttpGet]
[Route("pharmacies/{pharmacyId}/page/{page}/{filter?}")]
public async Task<CartTotalsDTO> GetProductsWithHistory(Guid pharmacyId, int page, string filter = null ,[FromUri] bool refresh = false)
{
return await Task.Factory.StartNew(() => delegateHelper.GetProductsWithHistory(CustomerContext.Current.GetContactById(pharmacyId), refresh));
}
Ich muss jedoch sagen, dass GetProductsWithHistory () eine ziemlich lange Operation ist. Wie kann ich angesichts meines Problems und meines Kontextes davon profitieren, wenn ich die webAPI-Operation asynchron mache?
c#
jquery
ajax
asp.net-web-api
async-await
David Jiménez Martínez
quelle
quelle
async Task<T>
. Denken Sie daran, AJAX wurde implementiert, bevor die TPL überhaupt existierte :)GetProductsWithHistoryAsync()
RückgabeTask<CartTotalsDTO>
. Das asynchrone Schreiben Ihres Controllers kann von Vorteil sein, wenn Sie die Aufrufe migrieren möchten, die auch asynchron sind. Dann profitieren Sie von den asynchronen Teilen, während Sie den Rest migrieren.Antworten:
In Ihrem speziellen Beispiel ist der Vorgang überhaupt nicht asynchron. Sie tun also asynchron über synchron. Sie geben nur einen Thread frei und blockieren einen anderen. Es gibt keinen Grund dafür, da alle Threads Thread-Pool-Threads sind (im Gegensatz zu einer GUI-Anwendung).
Von Soll ich synchrone Wrapper für asynchrone Methoden verfügbar machen?
Wenn Sie jedoch WebAPI-Aufrufe
async
ausführen, bei denen eine tatsächliche asynchrone Operation (normalerweise E / A) vorliegt, anstatt einen Thread zu blockieren, der sich befindet und auf ein Ergebnis wartet, kehrt der Thread zum Thread-Pool zurück und kann so eine andere Operation ausführen. Insgesamt bedeutet dies, dass Ihre Anwendung mit weniger Ressourcen mehr erreichen kann und die Skalierbarkeit verbessert.quelle
await Task.Run(() => CPUIntensive())
) ist in asp.net nutzlos. Sie gewinnen nichts davon. Sie geben nur einen ThreadPool-Thread frei, um einen anderen zu belegen. Es ist weniger effizient als nur die synchrone Methode aufzurufen.await Task.WhenAll
, um parallel auszuführen.Task.Run
wenn Sie Ihre Last auf mehreren Threads parallelisieren möchten, aber das bedeutet nicht "Async over Sync". "async over sync" verweist auf das Erstellen einer asynchronen Methode als Wrapper über eine synchrone. Sie können das im Zitat in meiner Antwort sehen.Ein Ansatz könnte sein (ich habe dies erfolgreich in Kundenanwendungen verwendet), dass ein Windows-Dienst die langwierigen Vorgänge mit Arbeitsthreads ausführt und dies dann in IIS ausführt, um die Threads freizugeben, bis der Blockierungsvorgang abgeschlossen ist: Hinweis, dies setzt voraus Die Ergebnisse werden in einer Tabelle (durch jobId gekennzeichnete Zeilen) gespeichert und einige Stunden nach der Verwendung durch einen saubereren Prozess bereinigt.
Um die Frage zu beantworten: "Wie kann ich angesichts meines Problems und meines Kontexts davon profitieren, wenn die webAPI-Operation asynchron ausgeführt wird?" Da es sich um eine "ziemlich lange Operation" handelt, denke ich eher an viele Sekunden als an ms, werden durch diesen Ansatz IIS-Threads freigegeben. Natürlich müssen Sie auch einen Windows-Dienst ausführen, der selbst Ressourcen beansprucht, aber dieser Ansatz könnte verhindern, dass eine Flut langsamer Abfragen Threads aus anderen Teilen des Systems stiehlt.
quelle