【问题标题】:To make Task.Delay() from Thread.Sleep() [duplicate]从 Thread.Sleep() 制作 Task.Delay() [重复]
【发布时间】: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。即使在示例中也要避免。

标签: c# multithreading


【解决方案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 缓存
猜你喜欢
  • 2021-12-22
  • 1970-01-01
  • 2019-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多