c#:链式异步方法

时间:2018-01-28 19:45:44

标签: c# async-await task method-chaining

我找到了一段显示如何链接异步方法的代码。这是代码:

    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)

有人可以解释一下吗?

1 个答案:

答案 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来说是完全矫枉过正的