C# 链接异步方法

C# 链接异步方法,c#,asynchronous,async-await,C#,Asynchronous,Async Await,我试图将我创建的几个异步方法链接在一起,我相信我对如何工作有一些基本的误解 以下是我的代码的表示: public async Task<bool> LoadFoo() { return await Foo.ReadAsync("bar").ContinueWith((bar) => { Foo.ReadAsync("baz").ContinueWith((baz) => { Foo.ReadAsync

我试图将我创建的几个异步方法链接在一起,我相信我对如何工作有一些基本的误解

以下是我的代码的表示:

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();
    });
}
public异步任务LoadFoo()
{
return wait Foo.ReadAsync(“bar”).ContinueWith((bar)=>
{
Foo.ReadAsync(“baz”).ContinueWith((baz)=>
{
Foo.ReadAsync(“qux”).ContinueWith((qux)=>
{
返回true;
});
返回true;
});
返回true;
});
}
公共空间
{
LoadFoo().ContinueWith((废话)=>
{
OtherLoadMethod();
});
}
现在,我希望当调用
LoadEverything()
时,
LoadFoo(“bar”、“baz”和“qux”)
中的所有
ReadAsync
方法将运行并完成,并且在它们全部完成之后,
LoadEverything
中的
ContinueWith
将运行,以便
OtherLoadMethod()
在“bar”、“baz”和“qux”方法完成之前不会执行

我实际看到的是,
LoadFoo
被调用,然后
OtherLoadMethod
开始运行,然后在
LoadFoo
中完成最后一个操作(“qux”
ReadAsync
ContinueWith

有人能帮我澄清一下这里的误解吗?为什么
OtherLoadMethod
的执行不等到
ReadAsync(“qux”)
完成并返回true

为什么OtherLoadMethod的执行不等待ReadAsync(“qux”)完成并返回true

因为这就是
wait
的工作原理。您注册的continuations就是:continuations。它们在当前方法中不同步执行。您正在告诉框架,当当前任务完成时,应该执行延续。通过
ContinueWith()
返回的
Task
对象,您可以在完成时观察完成情况。如果
ContinueWith()
方法在执行continuation之前被阻止,则甚至不需要返回
Task
对象

同样,您的
LoadFoo()
方法返回的
Task
表示该方法的总体完成情况,包括返回的
wait…ContinueWith()
。方法在继续操作完成之前返回,如果调用方需要等待继续操作完成,则需要使用返回的任务

尽管如此,我还是不明白你为什么要首先使用
ContinueWith()
。显然,您可以访问
wait
,这是处理延续的现代惯用方法。IMHO,您的代码应该是这样的(不清楚为什么返回的是
Task
,而不是
Task
,因为返回值仅为ever
true
,但我假设您可以自己计算出该部分):

public异步任务LoadFoo()
{
等待Foo.ReadAsync(“bar”);
等待Foo.ReadAsync(“baz”);
等待Foo.ReadAsync(“qux”);
返回true;
}
公共异步任务LoadEverything()
{
等待LoadFoo();
等待OtherLoadMethod();
}

您也可以使用
展开

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();
}
public异步任务LoadFoo()
{
等待Foo.ReadAsync(“bar”)
.ContinueWith(=>Foo.ReadAsync(“baz”)).Unwrap()
.ContinueWith(=>Foo.ReadAsync(“qux”)).Unwrap();
返回true;
}
公共异步任务LoadEverything()
{
等待LoadFoo().ContinueWith(=>OtherLoadMethod()).Unwrap();
}

谢谢你,彼得。为了确保我理解正确,Wait没有阻止线程正确吗?如果我要使用continuations(例如,如果我需要使用其中一个方法的返回值),我想理解这样的注释:“该方法在continuation完成之前返回,如果调用方需要等待continuation完成,则需要使用返回的任务。”调用LoadFoo()会不会.ContinueWith(…)是等待继续完成的调用方?“wait不会阻止线程”--这是正确的
await
标记方法中的一个点,在该点,该方法可能返回(如果等待表达式已经完成,则不会返回),并在等待表达式完成时恢复(继续)。线程将在此时返回调用方,或者继续执行当前方法。无论哪种方式,线程都保持未阻止状态“调用LoadFoo().ContinueWith(…)是否是等待继续完成的调用方?”--不,没有等待。
ContinueWith()
只需注册一个continuation,然后返回表示continuation完成的任务对象(在原始任务完成之前,任务对象无法完成)。不要使用
ContinueWith
;使用
wait
代替。您可以,但不应该。混合使用
wait
ContinueWith
会带来麻烦。组合
wait
ContinueWith
是因为两者都在当前计划程序上继续,但只有第一个在当前同步上下文上继续。此外,只有第一个打开了
aggregateeexception
s。答案中的代码可能不受这些复杂问题的影响,但它存在着吞咽
ReadAsync(“bar”)
ReadAsync(“baz”)
任务的可能异常的问题。只会观察到
ReadAsync(“qux”)
的例外情况。
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();
}