“await Task.Delay(1000)”会阻塞任何线程吗?

8

我已经了解到,建议使用Task.Delay()进行等待而不是阻塞调用线程(与Task.Delay().Wait()和Thread.Sleep()相反)。但是随着我的异步/等待知识的增加,我有一种感觉,即所有它所做的就是将可等待任务转移到另一个线程上执行。

因此,我是否理解正确:等待Task.Delay()不会阻塞调用线程,但它会阻塞某些线程,其中可等待任务被转移?

如果这个说法是正确的,那么你能否为我提供一种方法,让任务在等待时不会阻塞任何线程?


2
我有一篇博客文章,详细介绍了异步工作原理,而不会阻塞线程。链接为:http://blog.stephencleary.com/2013/11/there-is-no-thread.html。 - Stephen Cleary
2个回答

15
然而,它会阻塞某些线程,等待的任务会被转移?这取决于你所说的“阻塞”是什么意思。它不会导致任何线程沉睡1秒钟,或(更糟的是)自旋等待延迟完成。相反,它有效地安排一个定时器,在1秒钟后触发,然后执行由于await而注册的继续操作。
在某种程度上,await只是简单地转换为:
  • 调用可等待对象的GetAwaiter,以获取等待者。
  • 检查等待者是否已经完成 - 如果完成,就继续进行
  • 否则,使用等待者安排一个继续操作,并返回
  • 当等待者完成时,将调用继续操作,异步方法继续执行
聪明之处在于编译器保存状态和管理继续操作的方式,使得它从await表达式的末尾继续执行。

那么我的理解是,等待的Delay()任务所在的线程可以用来处理其他任务,而Delay()正在进行中? - cubrman
@cubrman: 你所说的“等待的 Delay() 任务被发送到哪里”是什么意思?Delay() 返回一个 Task,并且该任务在一秒钟后完成...并不像这是一个实际上正在执行任何操作的任务。如果您熟悉 System.Timers.Timer(或类似的内容),那么就像那样。 - Jon Skeet
@cubrman,“延迟”不会发生在进程上,而是发生在一个叫做时钟/定时器的硬件上。它不会以任何方式占用CPU程序逻辑部分的资源。 - Aron
2
@cubrman 你的问题就像是在问“当我设置早上的闹钟时,我的大脑的哪个部分会执行检查任务来确定何时醒来?” - Aron

0
所以我的理解是,当等待的Delay()任务被发送到的线程可以用来处理其他任务,而Delay()正在进行中?- cubrman 8月15日下午10:19
不,你不能在等待task.delay时做其他事情。下面的指令不会被执行,但线程也不会被阻塞!这意味着界面处理仍将正常工作,例如您将能够移动鼠标,单击按钮等。

但是你可以启动这个任务,做一些事情,然后再等待它。 - AyCe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接