C# 返回任务与返回等待的结果时出现异常

C# 返回任务与返回等待的结果时出现异常,c#,asynchronous,async-await,C#,Asynchronous,Async Await,我的理解是,如果您有一个async方法,其中唯一的wait是Task的最终返回,那么您可以删除async和wait关键字,只返回Task 例如: public async Task<object> Handle(object message) { var result = await Task.FromResult(message); return result; } async Task Main() { // outputs: Request v

我的理解是,如果您有一个
async
方法,其中唯一的
wait
Task
的最终返回,那么您可以删除
async
wait
关键字,只返回
Task

例如:

public async Task<object> Handle(object message)
{
    var result = await Task.FromResult(message);
    return result;
}
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);
    }
}
公共异步任务句柄(对象消息)
{
var result=等待任务。FromResult(消息);
返回结果;
}
变成

public Task<object> Handle(object message)
{
    return Task.FromResult(message);
}
公共任务句柄(对象消息)
{
返回Task.FromResult(消息);
}
但是,当方法包含多个WAIT语句时,这似乎不起作用

例如:

public async Task<object> Handle(object message)
{
    var result = await Task.FromResult(message);
    return result;
}
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);
    }
}
async Task Main()
{
//产出:请求
var requestHandlerAitingResult=(请求)等待新的HandlerAitingResult().Handle(新请求());
Debug.WriteLine(requestHandlerAitingResult.Description);
//InvalidCastException:无法将类型为“System.Threading.Tasks.Task`1[System.object]”的对象强制转换为类型为“Request”。
var requestHandlerReturnTask=(请求)等待新的HandlerReturningTask().Handle(新请求());
Debug.WriteLine(requestHandlerReturnTask.Description);
}
公共类请求
{
公共字符串Description=“Request”;
}
公共类handleRaitingResult
{
公共异步任务句柄(对象消息)
{
等待任务延迟(时间跨度从秒(1));
var result=wait Task.FromResult(消息);
返回结果;
}
}
公共类HandlerReturningTask
{
公共异步任务句柄(对象消息)
{
等待任务延迟(时间跨度从秒(1));
返回Task.FromResult(消息);
}
}
有人能告诉我为什么这不起作用吗

从根本上讲,两者之间的区别是什么

public class HandlerReturningTask
{
    public async Task<object> Handle(object message)
    {
        await Task.Delay(TimeSpan.FromSeconds(1));
        return Task.FromResult(message);
    }
}
公共类HandlerReturningTask
{
公共异步任务句柄(对象消息)
{
等待任务延迟(时间跨度从秒(1));
返回Task.FromResult(消息);
}
}

公共类HandlerReturningTask
{
公共异步任务句柄(对象消息)
{
等待任务延迟(时间跨度从秒(1));
返回等待任务。FromResult(消息);
}
}

公共类HandlerReturningTask
{
公共任务句柄(对象消息)
{
返回Task.FromResult(消息);
}
}

我仍然不确定我是否理解这个问题。但根据您的编辑:

基本上,[…
return Task.FromResult(message);
…]和[…
return wait Task.FromResult(message);
…]之间的区别是什么

理解
等待
的作用很重要:它表示方法中的一个点,方法可以在该点返回,然后在“等待”(例如
任务
)完成后,方法中的执行可以恢复

如果
任务
任务
,那么
等待
做的另一件事是,在方法中恢复执行时,为
任务
对象打开
T
值,即获取其
结果
属性值。
将等待
表达式计算到该值

最后,对于
async Task
方法,
return
语句使方法返回的
Task
对象(在第一个
wait
表达式中)在
return{value}
表达式中具有
Result

因此,在您的示例中,
返回Task.FromResult(message)
使
任务.Result
属性具有
任务类型的对象的值。稍后,
await
表达式计算该对象的
结果
属性值,您尝试将其强制转换为
请求
类型的对象,这当然是非法的

使用
返回等待任务.FromResult(消息)
导致首先计算
wait
表达式(因此
return
语句可以返回该表达式的结果),其效果是获取
Task.result
属性值。然后,该值由
return
语句返回,导致等待的
任务。Result
值成为最初传递给方法的
请求
对象。当然,当调用者中的
wait
打开包装时,可以将其转换回类型
Request


也就是说,通常直接返回值。将其包装在
任务
对象中,然后使用
等待
表达式立即将其展开是毫无意义的。编写
返回消息将得到完全相同的结果,但具有更可读性和更高效的代码。

生成的状态机处理任何可等待的数据。不仅仅是任务

如果您只处理一个任务,则可以绕过计算机生成的状态机的开销。但是,在出现异常的情况下,堆栈跟踪将不是您所期望的


异步方法的返回类型将始终是您返回的任务。

根据您对编译器为异步方法创建的状态机的理解,您能否首先解释一下为什么从您的角度来看它应该工作?我同意前面的评论,但不理解您的要求。您(应该)知道,
async
方法的
return
语句返回
Task
中类型为
T
的对象。在
句柄返回任务中,
T
对象
。然后,此对象由
wait
展开。因此,您返回一个
任务
对象,并尝试将其强制转换为
结果
。为什么要这样做?而不是
返回Task.FromResult(message)
,为什么您不只是
返回消息