J'ai l'opération suivante dans une API Web que j'ai créée:
// 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);
}
L'appel à ce service Web se fait via un appel Jquery Ajax de cette façon:
$.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);
}
});
J'ai vu des développeurs qui implémentaient l'opération précédente de cette façon:
// 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));
}
Je dois dire, cependant, que GetProductsWithHistory () est une opération assez longue. Compte tenu de mon problème et de mon contexte, comment le fait de rendre l'opération webAPI asynchrone me sera-t-il bénéfique?
c#
jquery
ajax
asp.net-web-api
async-await
David Jiménez Martínez
la source
la source
async Task<T>
. Rappelez-vous, AJAX a été implémenté avant même que le TPL existe :)GetProductsWithHistoryAsync()
retourTask<CartTotalsDTO>
. Il peut y avoir un avantage à écrire votre contrôleur de manière asynchrone si vous avez l'intention de migrer les appels qu'il effectue pour être également asynchrones; alors vous commencez à tirer parti des parties asynchrones au fur et à mesure que vous migrez le reste.Réponses:
Dans votre exemple spécifique, l'opération n'est pas du tout asynchrone, donc ce que vous faites est asynchrone sur synchronisation. Vous libérez juste un fil et en bloquez un autre. Il n'y a aucune raison à cela, car tous les threads sont des threads de pool de threads (contrairement à une application GUI).
De Dois-je exposer des wrappers synchrones pour les méthodes asynchrones?
Cependant, lors d'appels WebAPI
async
où il y a une opération asynchrone réelle (généralement des E / S) au lieu de bloquer un thread qui se trouve et attend un résultat, le thread retourne au pool de threads et donc capable d'effectuer une autre opération. Dans l'ensemble, cela signifie que votre application peut faire plus avec moins de ressources et cela améliore l'évolutivité.la source
await Task.Run(() => CPUIntensive())
) est inutile dans asp.net. Vous n'y gagnez rien. Vous libérez simplement un thread ThreadPool pour en occuper un autre. C'est moins efficace que d'appeler simplement la méthode synchrone.await Task.WhenAll
pour exécuter en parallèle.Task.Run
si vous souhaitez paralléliser votre charge sur plusieurs threads, mais ce n'est pas ce que signifie «asynchronisation sur synchronisation». "async over sync" fait référence à la création d'une méthode async en tant que wrapper sur une méthode synchrone. Vous pouvez voir le dans la citation dans ma réponse.Une approche pourrait être (j'ai utilisé cela avec succès dans les applications client) d'avoir un service Windows exécutant les longues opérations avec les threads de travail, puis de le faire dans IIS pour libérer les threads jusqu'à ce que l'opération de blocage soit terminée: Remarque, cela suppose les résultats sont stockés dans une table (lignes identifiées par jobId) et un processus plus propre les nettoie quelques heures après utilisation.
Pour répondre à la question: "Compte tenu de mon problème et de mon contexte, en quoi le fait de rendre l'opération webAPI asynchrone me sera-t-il bénéfique?" étant donné que c'est "une opération assez longue", je pense plusieurs secondes plutôt que ms, cette approche libère les threads IIS. De toute évidence, vous devez également exécuter un service Windows qui lui-même prend des ressources, mais cette approche pourrait empêcher un flot de requêtes lentes de voler des threads à d'autres parties du système.
la source