Gibt es gute Regeln für die Verwendung von Task.Delay im Vergleich zu Thread.Sleep ?
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.
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.
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.
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.