何时使用Task.Delay,何时使用Thread.Sleep?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了何时使用Task.Delay,何时使用Thread.Sleep?相关的知识,希望对你有一定的参考价值。

什么时候使用Task.DelayThread.Sleep有很好的规则?

  • 具体来说,是否有一个最小值来提供一个有效/高效的另一个?
  • 最后,由于Task.Delay导致异步/等待状态机上下文切换,是否有使用它的开销?
答案

如果要阻止当前线程,请使用Thread.Sleep

如果需要逻辑延迟而不阻塞当前线程,请使用Task.Delay

效率不应成为这些方法的首要考虑因素。它们的主要实际用途是作为I / O操作的重试计时器,其大小为秒而不是毫秒。

另一答案

Task.DelayThread.Sleep之间的最大区别是Task.Delay旨在异步运行。在同步代码中使用Task.Delay没有意义。在异步代码中使用Thread.Sleep是一个非常糟糕的主意。

通常你会用Task.Delay()关键字调用await

await Task.Delay(5000);

或者,如果您想在延迟之前运行一些代码:

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

猜猜这会印刷什么?运行0.0070048秒。如果我们将await delay移动到Console.WriteLine之上,它将打印运行5.0020168秒。

让我们看看与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");
    }
}

试着预测这会印刷什么......

异步:开始 异步:运行0.0070048秒 同步:开始 异步:运行5.0119008秒 异步:完成 同步:运行5.0020168秒 同步:完成

另外,有趣的是注意到Thread.Sleep更准确,ms准确度并不是真正的问题,而Task.Delay可能需要15-30ms最小。两个函数的开销与它们的ms精度相比是最小的(如果你需要更精确的东西,可以使用Stopwatch类)。 Thread.Sleep仍然绑定你的线程,Task.Delay释放它在你等待时做其他工作。

另一答案

如果当前线程被杀死并且你使用Thread.Sleep并且它正在执行那么你可能得到一个ThreadAbortException。使用Task.Delay,您可以随时提供取消令牌并优雅地杀死它。这就是我选择Task.Delay的一个原因。见http://social.technet.microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs-task-delay.aspx

我也同意效率在这种情况下并不是最重要的。

另一答案

我想补充一些东西。实际上,Task.Delay是一个基于计时器的等待机制。如果你看看source,你会找到一个Timer类的参考,它负责延迟。另一方面,Thread.Sleep实际上使当前线程进入睡眠状态,这样你只是阻塞并浪费一个线程。在异步编程模型中,如果你想在延迟之后发生某些事情(延续),你应该总是使用Task.Delay()

以上是关于何时使用Task.Delay,何时使用Thread.Sleep?的主要内容,如果未能解决你的问题,请参考以下文章

我是不是应该始终使用 Task.Delay 而不是 Thread.Sleep? [复制]

Thread.Sleep(2500) 与 Task.Delay(2500).Wait()

REST API 中的 Thread.sleep 与 Task.delay

C#中的Task.Delay()和Thread.Sleep()区别

Thread.Sleep x Task.Delay [重复]

从 Thread.Sleep() 制作 Task.Delay() [重复]