web-dev-qa-db-de.com

Wann benutzt man Task.Delay, wann Thread.Sleep?

Gibt es gute Regeln für die Verwendung von Task.Delay im Vergleich zu Thread.Sleep ?

  • Gibt es einen Mindestwert, um sicherzustellen, dass einer effektiver/effizienter ist als der andere?
  • Und da Task.Delay die Kontextumschaltung auf einer asynchronen/wartenden Zustandsmaschine verursacht, entsteht ein Mehraufwand für deren Verwendung?
317
Tom K.

Verwenden Sie Thread.Sleep, wenn Sie den aktuellen Thread blockieren möchten.

Verwenden Sie Task.Delay, wenn Sie eine logische Verzögerung wünschen, ohne den aktuellen Thread zu blockieren.

Effizienz sollte bei diesen Methoden nicht im Vordergrund stehen. In der Praxis werden sie hauptsächlich als Wiederholungszeitgeber für E/A-Vorgänge verwendet, die nicht in Millisekunden, sondern in der Größenordnung von Sekunden liegen.

318
Stephen Cleary

Der größte Unterschied zwischen Task.Delay und Thread.Sleep besteht darin, dass Task.Delay asynchron ausgeführt werden soll. Es ist nicht sinnvoll, Task.Delay in synchronem Code zu verwenden. Es ist eine sehr schlechte Idee, Thread.Sleep in asynchronem Code zu verwenden.

Normalerweise rufen Sie Task.Delay() mit dem Schlüsselwort await auf:

await Task.Delay(5000);

oder, wenn Sie vor der Verzögerung Code ausführen möchten:

var sw = new Stopwatch();
sw.Start();
Task delay = Task.Delay(5000);
Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds);
await delay;

Ratet mal, was dies drucken wird? Laufen für 0,0070048 Sekunden. Wenn wir stattdessen den await delay über den Console.WriteLine bewegen, wird Running für 5.0020168 Sekunden gedruckt.

Schauen wir uns den Unterschied mit Thread.Sleep an:

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");
    }
}

Versuchen Sie vorherzusagen, was dies ausgeben wird ...

async: Starten
async: Läuft für 0,0070048 Sekunden
Synchronisation: Starten
async: Läuft 5.0119008 Sekunden lang
async: Fertig
sync: Läuft für 5.0020168 Sekunden
Synchronisation: Fertig

Es ist auch interessant zu bemerken, dass Thread.Sleep viel genauer ist, ms-Genauigkeit ist nicht wirklich ein Problem, während Task.Delay mindestens 15-30 ms dauern kann. Der Aufwand für beide Funktionen ist im Vergleich zur ms-Genauigkeit minimal (verwenden Sie Stopwatch Class, wenn Sie etwas genaueres benötigen). Thread.Sleep bindet immer noch deinen Thread zusammen, Task.Delay lass ihn los, um andere Arbeiten zu erledigen, während du wartest.

200
Dorus

wenn der aktuelle Thread beendet wird und Sie Thread.Sleep verwenden und er ausgeführt wird, wird möglicherweise ThreadAbortException angezeigt. Mit Task.Delay können Sie immer einen Abbruch-Token bereitstellen und ihn ordnungsgemäß beenden. Das ist ein Grund, warum ich Task.Delay wählen würde. Siehe http://social.technet.Microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs-task-delay.aspx

Ich stimme auch zu, dass Effizienz in diesem Fall nicht an erster Stelle steht.

26
Balanikas

Ich möchte etwas hinzufügen. Tatsächlich ist Task.Delay ein zeitgesteuerter Wartemechanismus. Wenn Sie sich source ansehen, finden Sie einen Verweis auf eine Timer -Klasse, die für die Verzögerung verantwortlich ist. Andererseits schaltet Thread.Sleep den aktuellen Thread in den Ruhezustand, sodass Sie nur einen Thread blockieren und verschwenden. Im asynchronen Programmiermodell sollten Sie immer Task.Delay() verwenden, wenn etwas (Fortsetzung) nach einiger Verzögerung passieren soll.

20
crypted