Au cours des derniers jours, j'ai testé les nouvelles fonctionnalités de .net 4.5 et c # 5.
J'aime ses nouvelles fonctionnalités async / await. Auparavant, j'avais utilisé BackgroundWorker pour gérer des processus plus longs en arrière-plan avec une interface utilisateur réactive.
Ma question est: après avoir ces nouvelles fonctionnalités intéressantes, quand dois-je utiliser async / await et quand un BackgroundWorker ? Quels sont les scénarios communs pour les deux?
Réponses:
async / await est conçu pour remplacer des constructions telles que
BackgroundWorker
. Bien que vous puissiez certainement l' utiliser si vous le souhaitez, vous devriez pouvoir utiliser async / await, avec quelques autres outils TPL, pour gérer tout ce qui existe.Puisque les deux fonctionnent, cela dépend de la préférence personnelle que vous utilisez quand. Qu'est-ce qui est le plus rapide pour vous ? Qu'est-ce qui est plus facile à comprendre pour vous ?
la source
async
/await
permet également la programmation asynchrone sans threads de pool de threads.C'est probablement TL; DR pour beaucoup, mais je pense que comparer
await
avec,BackgroundWorker
c'est comme comparer des pommes et des oranges et mes pensées à ce sujet sont les suivantes:BackgroundWorker
est destiné à modéliser une tâche unique que vous souhaitez effectuer en arrière-plan, sur un thread de pool de threads.async
/await
est une syntaxe pour l'attente asynchrone sur les opérations asynchrones. Ces opérations peuvent ou non utiliser un thread de pool de threads ou même utiliser n'importe quel autre thread . Donc, ce sont des pommes et des oranges.Par exemple, vous pouvez faire quelque chose comme ce qui suit avec
await
:Mais, vous ne modéliseriez probablement jamais cela dans un travailleur d'arrière-plan, vous feriez probablement quelque chose comme ça dans .NET 4.0 (avant
await
):Remarquez la disjonction de l'élimination par rapport aux deux syntaxes et comment vous ne pouvez pas utiliser
using
sansasync
/await
.Mais vous ne feriez pas quelque chose comme ça avec
BackgroundWorker
.BackgroundWorker
est généralement destiné à modéliser une seule opération de longue durée dont vous ne souhaitez pas affecter la réactivité de l'interface utilisateur. Par exemple:Il n'y a vraiment rien avec lequel vous pouvez utiliser async / await, qui
BackgroundWorker
crée le thread pour vous.Maintenant, vous pouvez utiliser TPL à la place:
Dans ce cas, le
TaskScheduler
crée le thread pour vous (en supposant la valeur par défautTaskScheduler
), et pourrait utiliserawait
comme suit:À mon avis, une comparaison majeure est de savoir si vous faites état de progrès ou non. Par exemple, vous pourriez avoir un
BackgroundWorker like
ceci:Mais, vous ne traiteriez pas une partie de cela parce que vous feriez glisser-déposer le composant de travail d'arrière-plan sur l'aire de conception d'un formulaire - quelque chose que vous ne pouvez pas faire avec
async
/await
etTask
... c'est-à-dire que vous avez gagné ' t créer manuellement l'objet, définir les propriétés et définir les gestionnaires d'événements. vous souhaitez remplir uniquement le corps desDoWork
,RunWorkerCompleted
et desProgressChanged
gestionnaires d'événements.Si vous "convertissez" cela en async / await, vous feriez quelque chose comme:
Sans la possibilité de faire glisser un composant sur une surface Designer, c'est vraiment au lecteur de décider lequel est «meilleur». Mais, pour moi, c'est la comparaison entre
await
etBackgroundWorker
, pas si vous pouvez attendre des méthodes intégrées commeStream.ReadAsync
. par exemple, si vous utilisiezBackgroundWorker
comme prévu, il pourrait être difficile de le convertirawait
.Autres réflexions: http://jeremybytes.blogspot.ca/2012/05/backgroundworker-component-im-not-dead.html
la source
var t1 = webReq.GetResponseAsync(); var t2 = webReq2.GetResponseAsync(); await t1; await t2;
. Ce qui attendrait deux opérations parallèles. Attendent est beaucoup mieux pour asynchrone, mais des tâches séquentielles, OMI ...await Task.WhenAny(t1, t2)
pour faire quelque chose lorsque l'une ou l'autre tâche est terminée en premier. Vous voudrez probablement une boucle pour vous assurer que l'autre tâche se termine également. Habituellement, vous voulez savoir quand une tâche spécifique se termine, ce qui vous amène à écrire des séquences séquentiellesawait
.Voici une bonne introduction: http://msdn.microsoft.com/en-us/library/hh191443.aspx La section Threads est exactement ce que vous recherchez:
la source
BackgroundWorker est explicitement étiqueté comme obsolète dans .NET 4.5:
L'article MSDN «Programmation asynchrone avec Async et Await (C # et Visual Basic)» indique:
METTRE À JOUR
"pour les opérations liées aux E / S car le code est plus simple et vous n'avez pas à vous prémunir contre les conditions de concurrence " Quelles conditions de concurrence peuvent se produire, pourriez-vous donner un exemple? "
Cette question aurait dû être posée dans un message distinct.
Wikipedia a une bonne explication des conditions de course . La partie nécessaire de celui-ci est le multithreading et du même article MSDN Programmation asynchrone avec Async et Await (C # et Visual Basic) :
Autrement dit, "Les mots clés async et await ne provoquent pas la création de threads supplémentaires".
Pour autant que je me souvienne de mes propres tentatives lorsque j'étudiais cet article il y a un an, si vous avez exécuté et joué avec un échantillon de code du même article, vous pourriez tomber dans la situation où ses versions non asynchrones (vous pouvez essayer de convertir à vous-même) bloquer indéfiniment!
Vous pouvez également rechercher des exemples concrets sur ce site. Voici quelques exemples:
la source