J'essaye d'utiliser la async/await
fonctionnalité d'ASP.NET dans mon projet d'API Web. Je ne sais pas si cela fera une différence dans les performances de mon service API Web. Veuillez trouver ci-dessous le workflow et un exemple de code de mon application.
Flux de travail:
Application UI → Point de terminaison API Web (contrôleur) → Méthode d'appel dans la couche de service API Web → Appel d'un autre service Web externe. (Ici, nous avons les interactions DB, etc.)
Manette:
public async Task<IHttpActionResult> GetCountries()
{
var allCountrys = await CountryDataService.ReturnAllCountries();
if (allCountrys.Success)
{
return Ok(allCountrys.Domain);
}
return InternalServerError();
}
Couche de service:
public Task<BackOfficeResponse<List<Country>>> ReturnAllCountries()
{
var response = _service.Process<List<Country>>(BackOfficeEndpoint.CountryEndpoint, "returnCountries");
return Task.FromResult(response);
}
J'ai testé le code ci-dessus et fonctionne. Mais je ne suis pas sûr que ce soit l'utilisation correcte de async/await
. Veuillez partager vos pensées.
Réponses:
Gardez à l'esprit que le principal avantage du code asynchrone côté serveur est l' évolutivité . Cela ne rendra pas vos demandes plus rapides comme par magie. Je couvre plusieurs considérations "devrais-je utiliser
async
" dans mon article surasync
ASP.NET .Je pense que votre cas d'utilisation (appeler d'autres API) est bien adapté pour le code asynchrone, gardez simplement à l'esprit que «asynchrone» ne signifie pas «plus rapide». La meilleure approche consiste d'abord à rendre votre interface utilisateur réactive et asynchrone; cela rendra votre application sensation plus vite , même si elle est un peu plus lent.
En ce qui concerne le code, ce n'est pas asynchrone:
Vous auriez besoin d'une implémentation véritablement asynchrone pour bénéficier des avantages d'évolutivité de
async
:Ou (si votre logique dans cette méthode est vraiment juste un pass-through):
Notez qu'il est plus facile de travailler de "l'intérieur vers l'extérieur" plutôt que de "l'extérieur vers l'intérieur" comme ceci. En d'autres termes, ne commencez pas par une action de contrôleur asynchrone, puis ne forcez pas les méthodes en aval à être asynchrones. Au lieu de cela, identifiez les opérations naturellement asynchrones (appel d'API externes, requêtes de base de données, etc.) et rendez-les asynchrones au niveau le plus bas en premier (
Service.ProcessAsync
). Ensuite, laissez couler l'async
eau, rendant les actions de votre contrôleur asynchrones lors de la dernière étape.Et en aucun cas vous ne devez utiliser
Task.Run
dans ce scénario.la source
C'est correct, mais peut-être pas utile.
Comme il n'y a rien à attendre - pas d'appels aux API de blocage qui pourraient fonctionner de manière asynchrone - alors vous configurez des structures pour suivre le fonctionnement asynchrone (qui a une surcharge), mais vous n'utilisez pas cette capacité.
Par exemple, si la couche de service effectuait des opérations de base de données avec Entity Framework qui prend en charge les appels asynchrones:
Vous autoriseriez le thread de travail à faire autre chose pendant que la base de données était interrogée (et donc capable de traiter une autre demande).
Attendre a tendance à être quelque chose qui doit aller jusqu'au bout: il est très difficile de s'intégrer à un système existant.
la source
Vous n'utilisez pas efficacement async / await car le thread de demande sera bloqué lors de l'exécution de la méthode synchrone
ReturnAllCountries()
Le thread qui est assigné pour gérer une demande attendra pendant
ReturnAllCountries()
qu'il fonctionne.Si vous pouvez implémenter
ReturnAllCountries()
pour être asynchrone, alors vous verriez des avantages d'évolutivité. Cela est dû au fait que le thread peut être relâché dans le pool de threads .NET pour gérer une autre demande, pendantReturnAllCountries()
son exécution. Cela permettrait à votre service d'avoir un débit plus élevé, en utilisant plus efficacement les threads.la source
Je changerais votre couche de service en:
comme vous l'avez, vous exécutez toujours votre
_service.Process
appel de manière synchrone et ne tirez que très peu ou pas d'avantages à l'attendre.Avec cette approche, vous encapsulez l'appel potentiellement lent dans un
Task
, le démarrez et le renvoyez en attente. Vous avez maintenant l'avantage d'attendre le fichierTask
.la source
Service
n'est pas une méthode asynchrone et n'est pas attendue dans l'Service
appel lui-même. Je peux comprendre son argument, mais je ne pense pas qu'il s'applique ici.Task.Run
doit être évité sur ASP.NET. Cette approche supprimerait tous les avantages deasync
/await
et serait en fait pire sous charge qu'un simple appel synchrone.