await Task和Task.Result之间有什么区别?
await Task和Task.Result之间有什么区别?
public async Task GetName(int id) { Task nameTask = Task.Factory.StartNew(() => string.Format("Name matching id {0} = Developer", id)); return nameTask.Result; }
在上面的方法的返回语句中,我使用了Task.Result
属性。
public async Task GetName(int id) { Task nameTask = Task.Factory.StartNew(() => string.Format("Name matching id {0} = Developer", id)); return await nameTask; }
在这里,我使用了await Task
。如果我认为await将释放调用线程,而Task.Result
会阻塞它,那我就不会错了,是吗?
如果我认为 await 会释放调用线程而 Task.Result 会阻塞它,那么我应该是对的吧?
你是正确的,只要该任务没有同步完成。如果是同步完成,使用 Task.Result
或 await task
将同步执行,因为 await
将首先检查任务是否已完成。否则,如果任务没有完成,使用 Task.Result
将阻塞调用线程,而使用 await
将异步等待任务完成。另一个不同之处是异常处理。前者将传播 AggregationException
(其中可能包含一个或多个异常),而后者将解包并返回基础异常。
顺便提一下,使用异步包装器覆盖同步方法是不良实践,应该避免。 此外,在异步方法内部使用 Task.Result
会导致死锁,也应避免。
如果我认为await将释放调用线程而Task.Result将阻塞它,这样说是否正确?
一般而言,是的。 await task;
将“让出”当前线程。 task.Result
将阻塞当前线程。 await
是异步等待,Result
是阻塞等待。
还有一个更小的区别:如果任务以失败的状态(即异常)完成,则 await
将原样(重新)引发异常,而Result
将在AggregateException
中包装异常。
顺便提一下,避免使用Task.Factory.StartNew
。它几乎从来不是正确的方法。如果需要在后台线程上执行工作,请使用 Task.Run
。
如果正在进行动态任务并行,则Result
和StartNew
都是适当的;否则,应避免使用它们。如果进行异步编程,则两者都不适用。