我的理解是,如果您使用async
方法,await
最终返回Task
,则可以删除async
和{{1 }}关键字,只返回await
。
例如:
Task
变为
public async Task<object> Handle(object message)
{
var result = await Task.FromResult(message);
return result;
}
但是,当方法包含多个await语句时,这似乎不起作用。
例如:
public Task<object> Handle(object message)
{
return Task.FromResult(message);
}
有谁能告诉我为什么这不起作用?
从根本上说,
之间有什么区别async Task Main()
{
// outputs: Request
var requestHandlerAwaitingResult = (Request) await new HandlerAwaitingResult().Handle(new Request());
Debug.WriteLine(requestHandlerAwaitingResult.Description);
// InvalidCastException: Unable to cast object of type 'System.Threading.Tasks.Task`1[System.Object]' to type 'Request'.
var requestHandlerReturnTask = (Request) await new HandlerReturningTask().Handle(new Request());
Debug.WriteLine(requestHandlerReturnTask.Description);
}
public class Request
{
public string Description = "Request";
}
public class HandlerAwaitingResult
{
public async Task<object> Handle(object message)
{
await Task.Delay(TimeSpan.FromSeconds(1));
var result = await Task.FromResult(message);
return result;
}
}
public class HandlerReturningTask
{
public async Task<object> Handle(object message)
{
await Task.Delay(TimeSpan.FromSeconds(1));
return Task.FromResult(message);
}
}
和
public class HandlerReturningTask
{
public async Task<object> Handle(object message)
{
await Task.Delay(TimeSpan.FromSeconds(1));
return Task.FromResult(message);
}
}
和
public class HandlerReturningTask
{
public async Task<object> Handle(object message)
{
await Task.Delay(TimeSpan.FromSeconds(1));
return await Task.FromResult(message);
}
}
答案 0 :(得分:1)
我仍然不确定我理解这个问题。但根据你的编辑:
从根本上说,[...
return Task.FromResult(message);
...]和[...return await Task.FromResult(message);
之间有什么区别...]
了解await
的作用非常重要:它代表方法可以返回的方法中的一个点,然后在“等待”时可以在方法中执行(例如{{1} })完成。
如果Task
是Task
,那么Task<T>
做的另一件事是,在方法中恢复执行时,打开{{1}的await
值object,即获取其T
属性值。 Task<T>
表达式对该值的评估。
最后,对于Result
方法,await
语句会导致方法返回的async Task<T>
对象(在第一个return
表达式中)拥有Task<T>
await
表达式中的值。
因此,在您的示例中,Result
会使return {value}
属性具有return Task.FromResult(message);
类型的对象的值。稍后,Task<object>.Result
表达式会计算此对象的Task<Request>
属性值,并尝试将其强制转换为await
类型的对象,这当然是非法的。
使用Result
会首先评估Request
表达式(因此return await Task.FromResult(message);
语句可以返回该表达式的结果),这样可以获得await
} 适当的价值。然后,return
语句返回此值,导致等待的Task<Request>.Result
值成为最初传递给方法的return
对象。当然,当被调用者中的Task<object>.Result
打开时, 可以转换回类型Request
。
那就是说,通常你只是直接返回值。将它包装在Request
对象中,然后立即用await
表达式解包它是没有意义的。在该场景中编写Task<T>
将获得完全相同的结果,但代码更具可读性和效率。
答案 1 :(得分:0)
生成的状态机处理任何等待的。不仅是任务。
如果您只处理一项任务,则可以绕过计算机生成的状态机的开销。但是,在异常的情况下,堆栈跟踪将不是您所期望的。
异步方法的返回类型将始终是您返回的任务的任务。