Existe-t-il de bonnes règles pour savoir quand utiliser Task.Delay contre Thread.Sleep ?
- Plus précisément, existe-t-il une valeur minimale à prévoir pour que l'un soit efficace / efficient par rapport à l'autre?
- Enfin, étant donné que Task.Delay provoque un changement de contexte sur une machine d'état asynchrone / attente, y a-t-il un surcoût lié à son utilisation?
Réponses:
À utiliser
Thread.Sleep
lorsque vous souhaitez bloquer le thread actuel.À utiliser
Task.Delay
lorsque vous souhaitez un délai logique sans bloquer le thread actuel.L'efficacité ne doit pas être une préoccupation primordiale avec ces méthodes. Leur utilisation principale dans le monde réel est la temporisation des nouvelles tentatives pour les opérations d'E / S, qui sont de l'ordre des secondes plutôt que des millisecondes.
la source
Thread.Sleep
va bloquer le thread actuel qui provoque un changement de contexte. Si vous utilisez un pool de threads, cela peut également entraîner l'allocation d'un nouveau thread. Les deux opérations sont assez lourdes alors que le multitâche coopératif fourni parTask.Delay
etc. est conçu pour éviter tous ces frais généraux, maximiser le débit, permettre l'annulation et fournir un code plus propre.onesi: I would use
Thread.Sleep` pour attendre à l'intérieur d'une méthode synchrone. Cependant, je ne fais jamais cela dans le code de production; d'après mon expérience, tout ceThread.Sleep
que j'ai jamais vu est révélateur d'une sorte de problème de conception qui doit être corrigé correctement.La plus grande différence entre
Task.Delay
etThread.Sleep
est qu'ilTask.Delay
est destiné à s'exécuter de manière asynchrone. Cela n'a aucun sens d'utiliserTask.Delay
du code synchrone. C'est une TRÈS mauvaise idée à utiliserThread.Sleep
en code asynchrone.Normalement, vous appelez
Task.Delay()
avec leawait
mot - clé:ou, si vous souhaitez exécuter du code avant le délai:
Devinez ce que cela va imprimer? Fonctionne pendant 0,0070048 secondes. Si nous déplaçons ce qui
await delay
précède à laConsole.WriteLine
place, il imprimera Running pendant 5.0020168 secondes.Regardons la différence avec
Thread.Sleep
:Essayez de prédire ce que cela va imprimer ...
En outre, il est intéressant de noter que
Thread.Sleep
c'est beaucoup plus précis, la précision ms n'est pas vraiment un problème, alors qu'elleTask.Delay
peut prendre 15-30 ms minimum. Les frais généraux sur les deux fonctions sont minimes par rapport à la précision en ms qu'ils ont (utilisezStopwatch
Class si vous avez besoin de quelque chose de plus précis).Thread.Sleep
attache toujours votre fil,Task.Delay
relâchez-le pour effectuer d'autres travaux pendant que vous attendez.la source
Thread.Sleep()
consomme un thread entier qui pourrait autrement être utilisé ailleurs. Si de nombreuses tâches sont exécutées avec Thread.Sleep (), il y a de fortes chances d'épuiser tous les threads de pool de threads et d'entraver sérieusement les performances.async
méthodes car elles sont encouragées à être utilisées. C'est fondamentalement juste une mauvaise idée de s'exécuterThread.Sleep()
dans un thread threadpool, pas une mauvaise idée en général. Après tout, il y aTaskCreationOptions.LongRunning
quand vous empruntez laTask.Factory.StartNew()
route (bien que découragée) .await wait
Tasl.Delay
utilise le temporisateur système. Etant donné que "l'horloge système" coche "à un taux constant.", La vitesse de la coche du minuteur système est d'environ 16 ms, tout retard que vous demandez sera arrondi à un certain nombre de tiques de l'horloge système, compensé par le temps jusqu'au premier cocher. Consultez la documentation msdn surTask.Delay
docs.microsoft.com/en-us/dotnet/api/… et faites défiler vers le bas pour les remarques.si le thread actuel est tué et que vous l'utilisez
Thread.Sleep
et qu'il s'exécute, vous pouvez obtenir unThreadAbortException
. AvecTask.Delay
vous pouvez toujours fournir un jeton d'annulation et le tuer gracieusement. C'est une des raisons pour lesquelles je choisiraisTask.Delay
. voir http://social.technet.microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs-task-delay.aspxJe conviens également que l'efficacité n'est pas primordiale dans ce cas.
la source
await Task.Delay(5000)
. Quand je tue la tâche, j'obtiensTaskCanceledException
(et la supprime) mais mon fil est toujours vivant. Soigné! :)Je veux ajouter quelque chose. En fait,
Task.Delay
est un mécanisme d'attente basé sur une minuterie. Si vous regardez la source, vous trouverez une référence à uneTimer
classe qui est responsable du retard. D'un autre côté,Thread.Sleep
le thread actuel se met en veille, de cette façon vous bloquez et gaspillez un thread. Dans le modèle de programmation asynchrone, vous devez toujours utiliserTask.Delay()
si vous voulez que quelque chose (suite) se produise après un certain retard.la source