当前位置: 首页 > 编程语言 > C#

同时等待具有独立延续的多个异步调用分享

时间:2023-04-11 01:52:21 C#

C#学习教程:同时等待具有独立延续的多个异步调用以下天真的实现导致三个异步操作按顺序执行:privateasyncvoidbutton_Click(objectsender,RoutedEventArgse){cityTextBox.Text=awaitGetCityAsync();rankTextBox.Text=awaitGetRankAsync();有一个MSDN示例建议将任务的创建与其各自的await语句分开,允许它们并行运行:privateasyncvoidbutton_Click(objectsender,RoutedEventArgse){varcityTask=GetCityAsync();varrankTask=GetRankAsync();nameTextBox.Text=awaitnameTask;cityTextBox.Text=awaitcityTask;rankTextBox.Text=awaitrankTask;但是,这种方法的局限性在于任务延续仍然按顺序注册,这意味着第n个延续无法执行,直到它前面的所有n-1个延续都完成,即使它的任务可能首先完成。让异步任务并行运行的最佳模式是什么,但在各自的任务完成后每个继续运行?编辑:大多数答案建议等待Task.WhenAll,如下所示:privateasyncvoidbutton_Click(objectsender,RoutedEventArgse){varcityTask=GetCityAsync();varrankTask=GetRankAsync();等待任务.WhenAll(nameTask,cityTask,rankTask);nameTextBox.Text=nameTask.Result;cityTextBox.Text=cityTask.Result;rankTextBox.Text=rankTask.Result;但是,这不符合我的要求,因为我需要在任务完成后立即执行每个延续。例如,假设GetNameAsync需要5秒,GetCityAsync需要2秒,而GetRankAsync需要8秒。上面的实现将导致所有三个文本框仅在8秒后更新,即使nameTextBox和cityTextBox的结果之前已知。传统的做法是使用ContinueWith为每个异步任务注册相应的延续:privateasyncvoidbutton_Click(objectsender,RoutedEventArgse){等待Task.WhenAll(GetNameAsync().ContinueWith(nameTask=>{nameTextBox.Text=nameTask.Result;},uiScheduler),GetCityAsync().ContinueWith(cityTask=>{cityTextBox.Text=cityTask.Result;},uiScheduler),GetRankAsync().ContinueWith(rankTask=>{rankTextBox.Text=rankTask.Result;},uiScheduler));对于C#5,现在最好使用等待样式模式。这最容易通过将每个任务延续对分离到它自己的方法中来实现:}privateasyncTaskPopulateNameAsync(){nameTextBox。Text=awaitGetNameAsync();}privateasyncTaskPopulateCityAsync(){cityTextBox。文本=等待GetCityAsync();}privateasyncTaskPopulateRankAsync(){rankTextBox。Text=await(GetRankAsync);}定义所有这些琐碎的方法很快就会变得很麻烦,因此可以将它们压缩成一个异步lambda:=awaitGetNameAsync();})(),newFunc(async()=>{cityTextBox.Text=awaitGetCityAsync();})(),newFunc(async()=>{rankTextBox.Text=awaitGetRankAsync();})());如果经常使用这种模式,那么定义一个可以接受Funclambdas并执行它们的实用方法也会很有帮助,使我们的事件处理程序代码更清晰简洁易读:publicstaticTaskWhenAllTask??s(paramsFunc[]taskProducers){returnTask.WhenAll(taskProducers.Select(taskProducer=>taskProducer()));}privateasyncvoidbutton_Click(objectsender,RoutedEventArgse){awaitWhenAllTask??s(async()=>nameTextBox.Text=awaitGetNameAsync(),async()=>cityTextBox.Text=awaitGetCityAsync(),async()=>rankTextBox.Text=awaitGetRankAsync());}一个更简单的替代方法是:nameTextBox.Text=结果[0];nameCityBox.Text=结果[1];nameRankBox.Text=结果[2];}没有close,据我理解没有额外的状态机,需要查询三个异步资源,三个异步资源返回后才更新UI。如果这是正确的,则需要使用Task.WhenAll控件。像privateasyncvoidbutton_Click(objectsender,RoutedEventArgse){stringnametext=null;字符串城市文本=空;字符串排名文本=空;awaitTask.WhenAll(async()=>nametext=awaitGetNameAsync(),async()=>citytext=awaitGetCityAsync(),async()=>ranktext=awaitGetRankAsync());nameTextBox.Text=nametext;nameCityBox.Text=citytext;nameRankBox.Text=ranktext;}privateasyncvoidbutton_Click(objectsender,RoutedEventArgs){varnameTask=GetNameAsync();varcityTask=GetCityAsync();varrankTask=GetRankAsync();System.Threading.Tasks.Task.WaitAll(nameTask,cityTask,rankTask);nameTextBox.Text=nameTask.Result;城市文本框。Text=cityTask.Result;rankTextBox.Text=rankTask.Result;}更多详情:https://msdn.microsoft.com/pt-br/library/dd270695(v=vs.110).aspx以上是C#学习教程:同时等待多个异步调用共享的全部内容独立的延续。如果对你有用,需要了解更多C#学习教程,希望大家多多关注——本文收集自网络,不代表立场。如涉及侵权,请点击联系右侧管理员删除。如需转载请注明出处: