在循环内部,每个异步调用是否使用任务的continuewith链接到返回的任务?最佳做法是将所有异步调用收集在循环内的一个集合中,然后执行Task.WhenAll()。但是,如果你想知道在循环中遇到await时会发生什么,那么返回的Task包含什么?那些进一步的异步调用呢?它会创建新任务并将它们按顺序添加到返回的任务中吗?根据下面的代码privatevoidCallLoopAsync(){varloopReturnedTask=LoopAsync();}privateasyncTaskLoopAsync(){intcount=0;while(count<5){awaitSomeNetworkCallAsync();计数++;我假设的步骤是LoopAsync调用计数设置为零,代码进入while循环,检查条件SomeNetworkCallAsync,等待任务返回创建新任务/等待新任务返回CallLoopAsync()现在,只要有有足够的时间处理SomeNetworkCallAsync,如何/以何种方式执行下一行代码,如count++和更多SomeNetworkCallAsync?更新-基于JonHanna和StephenCleary:所以有一个任务,其实现将涉及对NetworkCallAsync的5次调用,但使用状态机意味着任务不需要明确链接到此即可工作。例如,这允许它根据任务的结果来决定是否打破循环等。虽然它们不是链式的,但每次调用都会等待前面的调用完成,因为我们使用了await(在状态m/c中,等待者.GetResult();)。它的行为就好像已经进行了五个连续的调用,并且它们一个接一个地执行(仅在前一个调用完成之后)。如果这是真的,我们必须更加小心我们如何编写异步调用。例如:而不是编写privateasyncTaskSomeWorkAsync(){awaitSomeIndependentNetworkCall();//2秒完成varresult1=awaitGetDataFromNetworkCallAsync();//2秒完成awaitPostDataToNetworkAsync(result1);//2秒完成}应该写privateTask[]RefactoredSomeWorkAsync(){vartask1=SomeIndependentNetworkCall();//2秒完成vartask2=GetDataFromNetworkCallAsync().ContinueWith(result1=>PostDataToNetworkAsync(result1)).Unwrap();//4秒完成returnnew[]{task1,task2};因此,我们可以说RefactoredSomeWorkAsync快了2秒,因为可能存在并行性//较慢,6秒}是否正确?-是的,除了“一路异步”之外,“一直积累任务”是一种很好的做法。此处进行类似讨论要生成类似于async和await的代码,如果这些关键字不存在,则需要如下代码:privatestructLoopAsyncStateMachine:IAsyncStateMachine{publicint_state;公共AsyncTaskMethodBuilder_builder;公共TestAsync_this;公共int_count;私人任务等待者_等待者;voidIAsyncStateMachine.MoveNext(){try{if(_state!=0){_count=0;转到安装后;}TaskAwaiter等待者=_等待者;_awaiter=默认值(TaskAwaiter);_state=-1;loopBack:awaiter.GetResult();等待者=默认(TaskAwaiter);_计数++;afterSetup:if(_count(refawaiter,refthis);return;}gotoloopBack;}_state=-2;_builder.SetResult();}catch(Exception异常){_state=-2;_builder.SetException(异常);返回;}}[DebuggerHidden]voidIAsyncStateMachine.SetStateMachine(IAsyncStateMachineparam0){_builder.SetStateMachine(param0);}}publicTaskLoopAsync(){LoopAsyncStateMachinestateMachineState;stateMachine._this=this;AsyncTaskMethodBuilderbuilder=AsyncTaskMethodBuilder.Create();stateMachine._builder=建造者;stateMachine._state=-1;builder.Start(参考状态机);返回生成器。任务;}(以上是基于使用async和await时发生的情况,除了它使用不能是有效C#类或字段名称的名称的结果,以及一些额外的属性,如果它的MoveNext()提醒您IEnumerator不是'完全不相关,await和async生成IAsyncStateMachine以实现任务的机制在很多方面都相似取决于yield如何生成IEnumerator。结果是来自AsyncTaskMethodBuilder的单个任务并使用LoopAsyncStateMachine(接近由异步生成的隐藏结构。它的MoveNext()方法在任务开始时首先被调用。然后它将在SomeNetworkCallAsync上使用SomeNetworkCallAsync。如果完成,它将进入下一阶段(递增计数等),否则它存储字段中的等待者。在后续使用中,它将被调用,因为SomeNetworkCallAsync()任务已返回,它将获得结果(在这种情况下为null,但如果它返回一个值,则可以是一个值)。然后它会尝试进一步循环并在等待尚未完成的任务时再次返回。当它最终达到计数5时,它在构建器CallSetResult()上设置由LoopAsync返回的任务的结果。所以有一个任务,其实现将涉及对NetworkCallAsync的5次调用,但使用状态机意味着任务不需要显式链接到此即可工作。例如,这可以让它根据任务的结果来决定是否打破循环等。当计数为零时,将创建一个新的任务,因为await和returnno,它不会。它会简单地调用异步方法,而不存储或返回结果。loopReturnedTask的值将存储loopReturnedTask的任务,与SomeNetworkCallAsync相同。等待SomeNetworkCallAsync();//调用,等待并忘记结果您可能想阅读有关异步等待的MSDN文章。当异步方法首先在await处产生时,它会返回一个Task(或Task)。这不是await接下来的任务;这是由异步方法创建的完全不同的任务。异步状态机控制着任务的生命周期。考虑它的一种方法是将返回的Task视为代表方法本身。返回的任务只会在方法完成时完成。如果该方法返回一个值,则将该值设置为任务的结果。如果方法抛出异常,状态机将捕获异常并将其放到任务中。因此,无需为返回的任务附加延续。在方法完成之前,返回的任务不会完成。将如何/以何种方式执行下一行代码,如count++和更多SomeNetworkCallAsync?我在异步介绍中解释了这一点。总之,当一个方法等待s时,它捕获一个“当前上下文”(SynchronizationContext.Current,除非它为null,在这种情况下它使用TaskScheduler.Current)。当await完成时,它将继续在该上下文中执行其异步方法。这就是技术上发生的事情;但在绝大多数情况下,它只是意味着:以上是C#学习教程:在循环内部,每个异步调用是否使用任务的continuewith链接到返回的任务?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
