根据Task<T>.Result
的原始文档,它导致等待线程被阻止。
处方是在请求.Wait()
之前打电话给.Result
。
这仍然是真的吗?如果不是,它什么时候改变了?
随后的问题:在.Wait()
之前调用.Result
(仍然)有用还是必要?
编辑:(更多背景/细节)
我在这里可能有一个严重的概念错误。但据我了解...调用.Wait()
会将任务返回给调度程序,并在任务完成后重新输入。有效地将车停在交叉路口中间(阻挡所有人)与停在路边,直到你准备继续行驶(而每个特别等待你的人也停在一边)。
Monitor,Semaphore等机制......将“阻止”所有尝试访问资源的线程。可能会不必要地破坏您的表现。当我第一次遇到.Result
(在async / await之前)时,文档和支持信息表示它是“阻塞”。这可能仍然是真的。
我想知道的是:
1)我对.Wait()
的理解是否正确?它是否将任务交还给调度程序重新进入?它可能没有以前,但我猜测可以实现编译器优化以允许这样做。
2)以下是否有任何真正的区别:
只需要打电话给.Result
。
var x = task.Result;
或者在调用.Wait
之前调用.Result
?
task.Wait();
var x = task.Result;
只需要调用Result
并调用Wait()
,然后调用Result
就没有区别了。如果任务尚未完成,它们都直接依赖于Task.InternalWait。
对于你问题的第一部分 - Wait()
不会“将任务返回到调度程序并重新输入”,这正是await
的用途。等待阻止它运行的线程,直到任务完成。但听起来你似乎关注互斥,而不是阻挡,这是不同的。
阻塞意味着一个线程已经执行了一些代码,导致它等待其他事情发生。该线程正在使用中,就像它正在进行实际工作一样,但它无所事事。这是不必要的浪费,特别是在Web应用程序这样的场景中,我们总是希望线程可用于执行代码来处理传入的请求,因为线程实际上是一种有限的资源,并且通常有等待使用不消耗的OS级设施的方法一个线程(这基本上是正确使用async/await
为你做的)。但是阻塞不会阻止其他线程在其中的一个线程内执行相同的代码。这是互斥,它明确地使用诸如Monitor或Semaphore之类的线程同步机制来限制或阻止在同一进程中多个线程之间对一段代码的并发访问。
Result
和Wait()
正在阻止,但不执行任何形式的互斥。