await Task <T>和Task <T> .Result有什么区别?

Yaw*_*aza 41 c# multithreading async-await

 public async Task<string> GetName(int id)
    {
        Task<string> nameTask =
            Task.Factory.StartNew(() => { return string.Format("Name matching id {0} = Developer", id); });
        return nameTask.Result;
    }
Run Code Online (Sandbox Code Playgroud)

在上面的方法return语句我使用Task.Result属性.

public async Task<string> GetName(int id)
    {
        Task<string> nameTask =
            Task.Factory.StartNew(() => { return string.Format("Name matching id {0} = Developer", id); });
        return await nameTask;
    }
Run Code Online (Sandbox Code Playgroud)

我在这里使用等待任务.如果我认为await将释放调用线程但是Task.Result将阻止它,我会不会错,它会是正确的吗?

Ste*_*ary 50

如果我认为await将释放调用线程但是Task.Result将阻止它,我会不会错,它会是正确的吗?

一般来说,是的.await task;将"屈服"当前线程.task.Result将阻止当前线程.await是异步等待; Result是一个阻塞等待.

还有一个更小的区别:如果任务在故障状态下完成(即有异常),那么await将(重新)按原样引发异常,但Result会将异常包装在一个AggregateException.

作为旁注,请避免Task.Factory.StartNew.它几乎不是正确的使用方法.如果您需要在后台线程上执行工作,请选择Task.Run.

无论ResultStartNew你正在做的是适当的动态任务并行 ; 否则,应该避免它们.如果您正在进行异步编程,则两者都不合适.


Yuv*_*kov 5

如果我认为 await 会释放调用线程但 Task.Result 会阻止它,我不会错,对吗?

你是对的,只要任务没有同步完成。如果是,则使用Task.Resultawait task将同步执行, asawait将首先检查任务是否已完成。否则,如果任务还没有完成,它会阻止调用线程Task.Result,而使用await一个同步等待的任务的完成。另一件不同的事情是异常处理。前者将传播一个AggregationException(可能包含一个或多个异常),而后者将解包它并返回底层异常。

作为旁注,在同步方法上使用异步包装器是不好的做法,应该避免。此外,Task.Result在异步方法中使用会导致死锁,也应该避免。

  • “在异步方法中使用 Task.Result 是导致死锁的原因”,如何会发生死锁,您能详细说明一下吗? (3认同)