J'ai une méthode dans l'application ASP.NET, qui prend beaucoup de temps à compléter. Un appel à cette méthode peut se produire jusqu'à 3 fois au cours d'une demande utilisateur, selon l'état du cache et les paramètres fournis par l'utilisateur. Chaque appel prend environ 1 à 2 secondes. La méthode elle-même est un appel synchrone au service et il n'y a aucune possibilité de remplacer l'implémentation.
Ainsi, l'appel synchrone au service ressemble à ceci:
public OutputModel Calculate(InputModel input)
{
// do some stuff
return Service.LongRunningCall(input);
}
Et l'utilisation de la méthode est (notez que l'appel de la méthode peut se produire plus d'une fois):
private void MakeRequest()
{
// a lot of other stuff: preparing requests, sending/processing other requests, etc.
var myOutput = Calculate(myInput);
// stuff again
}
J'ai essayé de changer la mise en œuvre de mon côté pour fournir un travail simultané de cette méthode, et voici ce à quoi je suis arrivé jusqu'à présent.
public async Task<OutputModel> CalculateAsync(InputModel input)
{
return await Task.Run(() =>
{
return Calculate(input);
});
}
Utilisation (une partie du code "faire d'autres choses" s'exécute simultanément avec l'appel au service):
private async Task MakeRequest()
{
// do some stuff
var task = CalculateAsync(myInput);
// do other stuff
var myOutput = await task;
// some more stuff
}
Ma question est la suivante. Dois-je utiliser la bonne approche pour accélérer l'exécution dans l'application ASP.NET ou est-ce que je fais un travail inutile en essayant d'exécuter du code synchrone de manière asynchrone? Quelqu'un peut-il expliquer pourquoi la deuxième approche n'est pas une option dans ASP.NET (si ce n'est vraiment pas le cas)? De plus, si une telle approche est applicable, dois-je appeler une telle méthode de manière asynchrone si c'est le seul appel que nous pourrions effectuer pour le moment (j'ai un tel cas, alors qu'il n'y a pas d'autre chose à faire en attendant la fin)?
La plupart des articles sur le net sur ce sujet couvrent l'utilisation de l' async-await
approche avec le code, qui fournit déjà des awaitable
méthodes, mais ce n'est pas mon cas. Iciest le bel article décrivant mon cas, qui ne décrit pas la situation des appels parallèles, refusant l'option d'envelopper l'appel de synchronisation, mais à mon avis ma situation est exactement l'occasion de le faire.
Merci d'avance pour l'aide et les conseils.
Task.Run
, le contenu est exécuté dans un autre thread, qui est extrait du pool de threads. Ensuite, il n'est pas du tout nécessaire d'envelopper les appels de blocage (comme le mien appel au service) dansRun
s, car ils consommeront toujours un thread chacun, qui sera bloqué pendant l'exécution de la méthode. Dans une telle situation, le seul avantage qui resteasync-await
dans mon cas est d'effectuer plusieurs actions à la fois. Corrigez-moi si j'ai tort, s'il-vous plait.Run
(ouParallel
) est la concurrence. Les opérations bloquent toujours chacune un thread. Puisque vous dites que le service est un service Web, je ne recommande pas d'utiliserRun
ouParallel
; à la place, écrivez une API asynchrone pour le service.BeginGetResponse
et en démarrer plusieurs, puis bloquer (de manière synchrone) jusqu'à ce qu'elles soient toutes complètes, mais ce type d'approche est délicat - voir blog.stephencleary.com/2012/07/dont-block-on -async-code.html et msdn.microsoft.com/en-us/magazine/mt238404.aspx . Il est généralement plus facile et plus propre à adopterasync
complètement, si possible.J'ai trouvé que le code suivant peut convertir une tâche pour qu'elle s'exécute toujours de manière asynchrone
et je l'ai utilisé de la manière suivante
Cela exécutera n'importe quelle tâche de manière asynchrone afin que vous puissiez les combiner dans des scénarios WhenAll, WhenAny et d'autres utilisations.
Vous pouvez également simplement ajouter le Task.Yield () comme première ligne de votre code appelé.
la source