C#关于在返回值为Task方法中使用Thread.Sleep引发的思考

本文探讨了在C#中,为何在返回Task的方法中使用Thread.Sleep会导致程序阻塞,而Task.Delay则不会。通过解析Thread.Sleep和Task.Delay的执行机制,解释了异步编程中线程调度、并发性和资源利用的重要性。同时,讨论了如何正确使用异步方法以避免阻塞,推荐在异步场景下使用Task.Delay。
摘要由CSDN通过智能技术生成

起因

最近有个小伙伴提出了一个问题,就是在使用.net core的BackgroundService的时候,对应的ExecuteAsync方法里面写如下代码,会使程序一直卡在当前方法,不会继续执行,代码如下:

public class BGService : BackgroundService
{
   
    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
   
        while (true)
        {
   
            Thread.Sleep(1000);
        }
    }
}

其实这个问题我们还是对Task和异步执行过程理解不够深入导致的,所以本篇文章笔者就以这个问题来对Task和异步方法执行过程来做源码的探究。
PS:本文只贴出重要的代码和注释,不是其全部的代码,读者多关注下注释。

解析

Thread.Sleep和Task.Delay的区别

  • Thread.Sleep分析
    它会挂起当前执行线程指定时间(调用了系统内核的方法),而这时候当前线程是不能做任何其他的事情,只能等待指定时间后再执行。最终执行的代码如下图:
private static void SleepInternal(int millisecondsTimeout)
{
   
    //这是Windows平台,不同平台调用的方法不一样
    Interop.Kernel32.Sleep((uint)millisecondsTimeout);
}
  • Task.Delay分析
    它的执行实际上是交给了TimerQueueTimer,也就是定时器队列(每个进程里,所有的timer执行都在一个TimerQueueTimer队列集合里面),在指定时间后回调方法,由ThreadPool中的线程执行。实际执行代码如下图:
public static Task Delay(int millisecondsDelay, CancellationToken cancellationToken)
{
   
    if (millisecondsDelay < -1)
    {
   
        ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.millisecondsDelay, ExceptionResource.Task_Delay_InvalidMillisecondsDelay);
    }
    //开始执行Delay方法
    return Delay((uint)millisecondsDelay, cancellationToken);
}

private static Task Delay(uint millisecondsDelay, CancellationToken cancellationToken) =>
    cancellationToken.IsCancellationRequested ? FromCanceled(cancellationToken) :
    millisecondsDelay == 0 ? CompletedTask :
                                          //它继承自DelayPromise,只不过加了CancellationToken
    cancellationToken.CanBeCanceled ? new DelayPromiseWithCancellation(millisecondsDelay, cancellationToken) :
    //最终执行这个
    new DelayPromise(millisecondsDelay);

internal DelayPromise(uint millisecondsDelay)
{
   
    if (millisecondsDelay != Timeout.UnsignedInfinite)
    {
   
    
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值