我发现了大量相关内容,但这些内容都是拐弯抹角的,但我始终无法找到答案。我几乎 100% 确定Task.Delay(int)
不使用线程,因为我可以在只有 16 个逻辑处理器的机器上运行此代码:
var tasks = new List<Task>();
for(int i = 1; i < 100000; i++) tasks.Add(Task.Delay(10000));
await Task.WhenAll(tasks);
并且需要十秒钟才能完成。我认为,如果它使用大约十万个线程,则需要更长的时间。
所以我的问题是如何Task.Delay(int)
work?不是以这样的方式这个标题不好的问题 https://stackoverflow.com/questions/47472420/how-does-task-delay-work-exactly表示,但从线程和硬件资源的角度来看。
在 .NET 的当前实现中,有一个“计时器线程”,它仅跟踪托管计时器实例并在适当的时间引发其事件。这个定时器线程将block https://github.com/dotnet/runtime/blob/8cd2d3077577bf14ae568f7d2fa9de2f1556d90c/src/libraries/System.Net.Requests/src/System/Net/TimerThread.cs#L557在其控制信号上,超时设置为下一个计时器的到期时间。控制信号用于添加/删除/更改计时器,因此当此阻塞请求超时时,计时器线程知道下一个计时器已触发。这是正常的线程阻塞操作,因此在内部,线程处于空闲状态并从调度程序队列中删除,直到阻塞操作完成或超时。这些操作的超时由操作系统调度程序的定时器中断处理。
所以从技术上讲,有一个线程,但它只是每个进程一个线程,而不是每个线程一个线程Task.Delay
.
我再次强调,这是在目前的实施.NET 的。人们还提出了其他解决方案,例如每个 CPU 一个计时器线程,或者计时器线程的动态池。也许它们被试验过并由于某种原因被拒绝,或者也许将来会采用替代解决方案。据我所知,这在任何地方都没有正式记录,所以这是一个实现细节。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)