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

Posted

技术标签:

【中文标题】从 Thread.Sleep() 制作 Task.Delay() [重复]【英文标题】:To make Task.Delay() from Thread.Sleep() [duplicate] 【发布时间】:2017-11-09 16:06:19 【问题描述】:

我可以假设doTaskdoTask2 做同样的工作并且可能在代码中被替换吗?

    public async static void doTask()
    
        await Task.Delay(TimeSpan.FromSeconds(5));
    


    public async static void doTask2()
    
        await Task.Factory.StartNew(() =>
        
            Thread.Sleep(TimeSpan.FromSeconds(5));
        );
    

根据我的实验,这两个函数的作用相同。

【问题讨论】:

第一个允许为任务服务的线程返回操作系统。第二个阻塞线程。第一个更好。 其实真的different 顺便说一句,async void considered harmful。即使在示例中也要避免。 【参考方案1】:

它们之间的一个非常非常重要的区别是Thread.Sleep()在一段时间内阻塞线程,这意味着线程将无法用于线程池,而Task.Delay()创建一个任务并立即释放线程,以便其他任务可以使用那个线程。

Thread.Sleep 可能很容易导致线程饥饿

为了演示(注意我已将返回类型更改为Task):

static void Main(string[] args)

    Task.WaitAll(Enumerable.Range(0, 1000).Select(o => doTask()).ToArray());
    Console.WriteLine("1");
    Task.WaitAll(Enumerable.Range(0, 1000).Select(o => doTask2()).ToArray());
    Console.WriteLine("2");


public async static Task doTask() => await Task.Delay(TimeSpan.FromSeconds(1));
public async static Task doTask2() => await Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(1)));

您会很快看到1,但要出现2 需要很多时间(在我的 8 核 CPU 上需要几分钟)。

经验法则:使用线程 - 使用 Thread.Sleep,使用任务 - 坚持使用 Task.Delay

【讨论】:

添加到此线程切换和 CPU 缓存失效 - 如果该方法确实有用,Sleep() 将强制线程切换从线程数据中清空 CPU 缓存

以上是关于从 Thread.Sleep() 制作 Task.Delay() [重复]的主要内容,如果未能解决你的问题,请参考以下文章

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

如果 Task.Delay 优于 Thread.Sleep,为啥本书中的示例使用 Thread.Sleep?

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

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

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

Thread.Sleep x Task.Delay [重复]