在调用Wait之前实际上访问任务的结果是什么?

问题描述 投票:-1回答:2

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”。我已在问题中解决此问题,但在此保留评论和答案以供参考。

c# task-parallel-library
2个回答
2
投票

那么访问Task上的任何此类属性是否充当调用Task.Wait()的快捷方式?

来自the docs

访问[Result]属性的get访问器将阻塞调用线程,直到异步操作完成为止;它等效于调用Wait方法。

但是,您的测试并未达到您认为的目的。

Task.Delay(..)返回Task,该时间在指定的时间后完成。它不会阻塞调用线程。

因此() => { Task.Delay(5000); return 123; }只需创建一个新的Task(将在5秒钟内完成),然后将其丢弃并立即返回123

您可以:

  1. 通过执行Task.Delay(5000).Wait()来阻止调用线程(与Thread.Sleep(5000)相同)
  2. 异步等待从Task返回的Task.Delay完成:Task.Run(async () => { await Task.Delay(5000); return 123; })

1
投票

测试不等待Task.Delay(),因此它会立即返回。应该是:

var r = Task.Run(async  () => { await Task.Delay(5000); return 123; }).Result;

Result的行为已得到很好的定义-如果任务尚未完成,它将阻塞直到它完成为止。访问其他任务属性不会被阻止

© www.soinside.com 2019 - 2024. All rights reserved.