链接异步方法

时间:2017-08-14 00:31:48

标签: c# asynchronous async-await

我试图将我创建的一些异步方法联系在一起,我相信对于我的工作原理存在一些根本性的误解

这是我的代码的代表:

public async Task<bool> LoadFoo()
{
    return await Foo.ReadAsync("bar").ContinueWith((bar) =>
    {
        Foo.ReadAsync("baz").ContinueWith((baz) =>
        {
            Foo.ReadAsync("qux").ContinueWith((qux) =>
            {
                return true;
            });

            return true;
        });

        return true;
    });
}

public void LoadEverything()
{
    LoadFoo().ContinueWith((blah) =>
    {
        OtherLoadMethod();
    });
}

现在我希望在LoadEverything()被调用时,ReadAsync中的所有LoadFoo ("bar", "baz" and "qux")方法都会运行并完成,并且在它们全部完成后,.ContinueWith在{ {1}}会运行,以便LoadEverything不会执行,直到&#34;&#34;,&#34; baz&#34;和&#34; qux&#34; OtherLoadMethod()方法已完成。

我实际看到的是ReadAsync被调用,然后LoadFoo开始运行,然后才开始OtherLoadMethod LoadFoo的{​​{1}} 34; qux&#34; ContinueWith)。

有人可以帮我解决我的误会吗?为什么ReadAsync的执行不会等到OtherLoadMethod完成并返回true?

2 个答案:

答案 0 :(得分:9)

  

为什么执行OtherLoadMethod会等到ReadAsync(“qux”)结束并返回true?

因为这是await的工作方式。您注册的延续只是: continuations 。它们不是在当前方法中同步执行的。您告诉框架当前任务完成时,应该执行继续。 Task返回的ContinueWith()对象允许您在发生时查看完成情况。如果Task方法被阻塞直到执行继续,则无需返回ContinueWith()个对象。

同样,Task<bool>方法返回的LoadFoo()表示该方法的整体完成情况,包括您要返回的await...ContinueWith()。该方法在完成延续之前返回,如果需要等待继续完成,则调用者应使用返回的任务。

所有这一切,我不明白为什么你首先使用ContinueWith()。您显然可以访问await,这是处理延续的现代惯用方法。恕我直言,你的代码看起来应该是这样的(不清楚你为什么要返回Task<bool>而不是Task,因为返回值只是true,但我想你可以想象那部分你自己):

public async Task<bool> LoadFoo()
{
    await Foo.ReadAsync("bar");
    await Foo.ReadAsync("baz");
    await Foo.ReadAsync("qux");

    return true;
}

public async Task LoadEverything()
{
    await LoadFoo();
    await OtherLoadMethod();
}

答案 1 :(得分:-1)

您也可以使用Unwrap

public async Task<bool> LoadFoo()
{
    await Foo.ReadAsync("bar")
        .ContinueWith(_ => Foo.ReadAsync("baz")).Unwrap()
        .ContinueWith(_ => Foo.ReadAsync("qux")).Unwrap();
    return true;
}

public async Task LoadEverything()
{
    await LoadFoo().ContinueWith(_ => OtherLoadMethod()).Unwrap();
}