【发布时间】:2020-02-05 12:33:32
【问题描述】:
var task = Task.Run(() => DoSomeStuff()).Result;
引擎盖下发生了什么?
我做了一个小测试:
using System;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
var r = Task.Run( () => {Thread.Sleep(5000); return 123; }).Result;
Console.WriteLine(r);
}
}
它在 5 秒后打印“123”。那么访问Task 上的任何此类属性是否可以作为调用Task.Wait() 的快捷方式,即这样做安全吗?
以前我的代码称为Task.Delay(5000),它立即返回“123”。我在我的问题中解决了这个问题,但把它留在这里,因为 cmets 和答案引用它。
【问题讨论】:
-
它就像调用了
.Wait()一样阻塞。Task.Delay()的测试永远不会等待。不,访问任何属性都不是Wait()的快捷方式。Result和Wait()的行为定义明确 - 当我们不想要任何结果时,Wait()会阻塞。Result阻塞并返回结果 -
尚未在答案中提出的重点是:除非您知道任务已经完成,否则切勿使用 Wait 或 Result。很容易陷入这样一种情况,即任务已将工作安排到您刚刚进入休眠状态的线程上,而现在任务永远不会完成,线程永远不会唤醒,因为将任务的工作一直在睡觉,直到完成!异步被设计为异步;强制它同步是危险的。
-
@EricLippert 只等待已经发生的事情?这似乎相当不直观!
-
该评论确实应该是一个答案。将添加一个。