C# 如何延迟异步方法结果的转换?

C# 如何延迟异步方法结果的转换?,c#,async-await,C#,Async Await,假设我正在包装一个复杂的API,并且我有自己的结果类型,我希望从包装底层异步方法的异步方法中返回这些结果类型 interface IMyWrapper { Task<MyResult> GetResultAsync(string arg); } 我假设调用A在调用B开始之前完成,它在调用C开始之前完成。这否定了异步代码的全部要点 我的假设准确吗,或者我遗漏了什么,如果我遗漏了什么 如果我没有遗漏什么,我该如何延迟或任务化(我相信这是一个词)将他们的结果转换为我的结果类型 实

假设我正在包装一个复杂的API,并且我有自己的结果类型,我希望从包装底层异步方法的异步方法中返回这些结果类型

interface IMyWrapper
{
    Task<MyResult> GetResultAsync(string arg);
}
我假设
调用A
调用B
开始之前完成,它在
调用C
开始之前完成。这否定了异步代码的全部要点

我的假设准确吗,或者我遗漏了什么,如果我遗漏了什么

如果我没有遗漏什么,我该如何延迟或任务化(我相信这是一个词)将他们的结果转换为我的结果类型

实际考虑

真正的方法有时调用底层api,有时执行其他操作。
底层api返回的对象是一个没有公共构造函数的具体类型,因此我无法创建一个并返回它。

以便等待所有需要使用的任务。taskwhalll

await Task.WhenAll(apiTask,taskA,taskB);

//All tasks have been completed and it's safe to access the result.
DoSomethingEsle(apiTask.Result, taskA.Result, taskB.Result);

为了等待所有任务,您需要使用taskwhalll

await Task.WhenAll(apiTask,taskA,taskB);

//All tasks have been completed and it's safe to access the result.
DoSomethingEsle(apiTask.Result, taskA.Result, taskB.Result);

在上面的代码中,首先要完成的是调用C,然后是调用A,最后是调用B

var api = await apiTask; // Call C
var a = await taskA; // Call A
var b = await taskB; // Call B

在上面的代码中,首先要完成的是调用C,然后是调用A,最后是调用B

var api = await apiTask; // Call C
var a = await taskA; // Call A
var b = await taskB; // Call B

不,你的假设是错误的。任务B(甚至任务C)可以在任务A完成之前开始,并且可以以任何顺序完成。您唯一可以保证的是,一旦所有任务完成,就会调用“DoSomethingElse”。

不,您的假设是错误的。任务B(甚至任务C)可以在任务A完成之前开始,并且可以以任何顺序完成。您唯一可以保证的是,一旦所有任务完成,就会调用“DoSomethingElse”

我假设调用A在调用B开始之前完成,它在调用C开始之前完成

这种假设是不正确的。调用A可以在调用B开始之前完成,如果它完成得非常快,但没有什么强迫它完成的,所以几乎肯定不会

我的假设准确吗,或者我遗漏了什么,如果我遗漏了什么

您似乎忽略了当您调用异步方法时,它返回时不一定完成。
async
方法的要点在于,它在实际工作完成之前返回,并且工作在将来的某个时间点完成。在一行中调用多个异步方法不会强制第一个方法在下一个开始之前完成;这只适用于同步代码

我假设调用A在调用B开始之前完成,它在调用C开始之前完成

这种假设是不正确的。调用A可以在调用B开始之前完成,如果它完成得非常快,但没有什么强迫它完成的,所以几乎肯定不会

我的假设准确吗,或者我遗漏了什么,如果我遗漏了什么


您似乎忽略了当您调用异步方法时,它返回时不一定完成。
async
方法的要点在于,它在实际工作完成之前返回,并且工作在将来的某个时间点完成。在一行中调用多个异步方法不会强制第一个方法在下一个开始之前完成;这只适用于同步代码。

但是
wrapper.GetResultAsync
有一个wait,它不会阻止其他方法被调用?但是
wrapper.GetResultAsync
有一个wait,它不会阻止其他方法被调用?谢谢,但这确实不能回答问题中的任何问题。不,您不需要在所有时使用
。像他那样等待所有的任务是很好的。调用A将运行到它离开当前线程的点。例如,如果theirObject.GetResultAsync对服务器进行Web API调用,线程可以自由地开始处理调用B。在这一点上,它将开始创建MyResult。它可能是呼叫A,但也可能是呼叫B。通过使用Task.whalll,您正在等待所有3项任务完成,然后才能访问结果。@M.Tovbin:如果您在回答中添加了该评论,我会对其进行投票(顺便说一句,我没有投反对票).@M.Tovbin使用
WhenAll
与在启动所有3个后依次等待所有3个没有什么不同,就像他在原始代码中所做的那样。谢谢,但这确实不能回答问题。不,您不需要使用
WhenAll
。像他那样等待所有的任务是很好的。调用A将运行到它离开当前线程的点。例如,如果theirObject.GetResultAsync对服务器进行Web API调用,线程可以自由地开始处理调用B。在这一点上,它将开始创建MyResult。它可能是呼叫A,但也可能是呼叫B。通过使用Task.whalll,您正在等待所有3项任务完成,然后才能访问结果。@M.Tovbin:如果您在回答中添加了该评论,我会对其进行投票(顺便说一句,我没有投反对票).@M.Tovbin在启动所有3个之后,使用
whalll
与依次等待所有3个没有什么不同,就像他在最初的代码中所做的那样。事实上,我在几个月前开始使用async并等待的时候就向自己证明了这一点,但现在我已经开始使用它了,我已经把自己弄糊涂了。谢谢Servy。几个月前,当我开始使用async并等待时,我已经向自己证明了这一点,但现在我已经开始使用它了,我已经把自己弄糊涂了。谢谢Servy。