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
,因为返回值仅为evertrue
,但我假设您可以自己计算出该部分):
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();
}