web-dev-qa-db-fra.com

Quand utiliser Task.Delay, quand utiliser Thread.Sleep?

Existe-t-il de bonnes règles indiquant quand utiliser Task.Delay ou Thread.Sleep ?

  • Plus précisément, existe-t-il une valeur minimale pour que l’un soit efficace/efficient par rapport à l’autre?
  • Enfin, puisque Task.Delay provoque la commutation de contexte sur une machine à états asynchrone/wait, existe-t-il une surcharge d'utilisation?
317
Tom K.

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.

318
Stephen Cleary

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.

200
Dorus

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.

26
Balanikas

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.

20
crypted