我找到了一段显示如何链接异步方法的代码。这是代码:
public static class ExtensionMethod
{
public static async Task<TResult> MapAsync<TSource, TResult>(
this Task<TSource> @this,
Func<TSource, Task<TResult>> fn)
{
return await fn(await @this);
}
}
public partial class Program
{
public async static Task<int> FunctionA
(int a) => await Task.FromResult(a * 1);
public async static Task<int> FunctionB(
int b) => await Task.FromResult(b * 2);
public async static Task<int> FunctionC(
int c) => await Task.FromResult(c * 3);
public async static void AsyncChain()
{
int i = await FunctionC(10)
.MapAsync(FunctionB)
.MapAsync(FunctionA);
Console.WriteLine("The result = {0}", i);
}
}
但我不明白为什么在扩展方法MapAsync
中我们有await fn(await @this)
?
有人可以解释一下吗?
答案 0 :(得分:0)
这是因为为了获得前一次调用的值(在这种情况下是存储在Task @this
中的值),必须等待它。由于await
现在正在方法中使用,并且必须将其标记为async
,因此您现在不能再仅仅从fn
返回结果,因为它是一个任务。 (因为我确定你知道,并且用非常简单的术语来说,将方法标记为异步意味着方法签名忽略了Task而只是想要泛型类型的实例作为返回,如果它不使用Task
的genric版本。)
在回复你关于链接同步和异步方法的评论时,这种使用Task的方法仍然适用于同步方法,你只需通过将结果包装在任务中来假装它的异步(已标记为已完成)。像这样:
public async static Task<int> AsyncFunction(int x)
=> await SomeAsyncMethodThatReturnsTaskOfInt();
public static Task<int> SyncFunction(int x)
=> Task.FromResult(SomeSyncMethodThatReturnsInt());
public async static void AsyncChain()
{
int i = await AsyncFunction(10)
.MapAsync(SyncFunction);
Console.WriteLine("The result = {0}", i);
}
你可以从FunctionA,FunctionB和FunctionC定义中删除所有async / awaits,因为它们只能返回任务。
Stephen Cleary在Eliding await上有一篇很好的文章,可以更好地解释当你应该和不应该使用await时,方法所做的唯一事情就是返回Task
。
说了这么多,Gusman的评论是完全正确的,这对于一个相当简单的ContinueWith来说是完全矫枉过正的