Existe-t-il de bonnes règles indiquant quand utiliser Task.Delay ou Thread.Sleep ?
Utilisez Thread.Sleep
lorsque vous souhaitez bloquer le fil actuel.
Utilisez Task.Delay
lorsque vous souhaitez un délai logique sans bloquer le thread actuel.
L'efficacité ne devrait pas être une préoccupation primordiale avec ces méthodes. Leur principale utilisation dans le monde réel consiste à utiliser des temporisateurs de nouvelle tentative pour les opérations d'E/S, qui sont de l'ordre de quelques secondes plutôt que de quelques millisecondes.
La plus grande différence entre Task.Delay
et Thread.Sleep
est que Task.Delay
est destiné à être exécuté de manière asynchrone. Il n’a pas de sens d’utiliser Task.Delay
en code synchrone. C'est une très mauvaise idée d'utiliser Thread.Sleep
en code asynchrone.
Normalement, vous appelerez Task.Delay()
avec le mot clé await
:
await Task.Delay(5000);
ou, si vous voulez exécuter du code avant le délai:
var sw = new Stopwatch();
sw.Start();
Task delay = Task.Delay(5000);
Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
await delay;
Devinez quoi cela va imprimer? Courir pendant 0,0070048 secondes. Si nous déplaçons plutôt le await delay
au-dessus du Console.WriteLine
, il sera imprimé en cours d'exécution pendant 5,0020168 secondes.
Regardons la différence avec Thread.Sleep
:
class Program
{
static void Main(string[] args)
{
Task delay = asyncTask();
syncCode();
delay.Wait();
Console.ReadLine();
}
static async Task asyncTask()
{
var sw = new Stopwatch();
sw.Start();
Console.WriteLine("async: Starting");
Task delay = Task.Delay(5000);
Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
await delay;
Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
Console.WriteLine("async: Done");
}
static void syncCode()
{
var sw = new Stopwatch();
sw.Start();
Console.WriteLine("sync: Starting");
Thread.Sleep(5000);
Console.WriteLine("sync: Running for {0} seconds", sw.Elapsed.TotalSeconds);
Console.WriteLine("sync: Done");
}
}
Essayez de prédire ce que cela va imprimer ...
async: démarrage
async: en cours d'exécution pendant 0,0070048 secondes
sync: Démarrage
async: en cours d'exécution pendant 5,0119008 secondes
async: Fait
sync: en cours d'exécution pendant 5,0020168 secondes
sync: Fait
Aussi, il est intéressant de noter que Thread.Sleep
est beaucoup plus précis, la précision de ms n’est pas vraiment un problème, alors que Task.Delay
peut prendre 15 à 30 ms. La surcharge sur les deux fonctions est minime comparée à la précision ms qu'elles ont (utilisez Stopwatch
Class si vous avez besoin de quelque chose de plus précis). Thread.Sleep
lie toujours votre fil, Task.Delay
relâchez-le pour effectuer un autre travail pendant que vous attendez.
si le thread actuel est tué et que vous utilisez Thread.Sleep
et qu'il est en cours d'exécution, vous pouvez obtenir un ThreadAbortException
. Avec Task.Delay
vous pouvez toujours fournir un jeton d'annulation et le tuer gracieusement. C’est une des raisons pour lesquelles je choisirais Task.Delay
. voir http://social.technet.Microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs-task-delay.aspx
Je conviens également que l'efficacité n'est pas primordiale dans ce cas.
Je veux ajouter quelque chose. En fait, Task.Delay
est un mécanisme d'attente basé sur un minuteur. Si vous regardez source , vous trouverez une référence à une classe Timer
qui est responsable du retard. D'autre part, Thread.Sleep
fait en sorte que le thread actuel soit mis en veille, de cette façon vous bloquez et gaspillez un seul thread. Dans le modèle de programmation async, vous devez toujours utiliser Task.Delay()
si vous voulez que quelque chose (suite) arrive après un certain délai.