c# – 如何并行执行嵌套的异步等待代码,同时在等待延续中保持相​​同的线程?

c# – 如何并行执行嵌套的异步等待代码,同时在等待延续中保持相​​同的线程?,第1张

概述这可能是我写过的最糟糕的StackOverflow标题.我实际上要做的是执行一个异步方法,该方法在同步方法中多次并行使用async / await约定(并且本身包含额外的await调用),同时在整个执行每个分支的过程中保持相同的线程.并行执行,包括所有等待延续.换句话说,我想同步执行一些异步代码,但我想多次并行执行.现在你可以看到为什么标题太糟糕了.也许最好用一些代码来说明…… 假设我有以下内容: 这可能是我写过的最糟糕的StackOverflow标题.我实际上要做的是执行一个异步方法,该方法在同步方法中多次并行使用async / await约定(并且本身包含额外的await调用),同时在整个执行每个分支的过程中保持相同的线程.并行执行,包括所有等待延续.换句话说,我想同步执行一些异步代码,但我想多次并行执行.现在你可以看到为什么标题太糟糕了.也许最好用一些代码来说明……

假设我有以下内容:

public class MyAsyncCode{    async Task MethodA()    {        // Do some stuff...        await MethodB();        // Some other stuff    }    async Task MethodB()    {        // Do some stuff...        await MethodC();        // Some other stuff    }    async Task MethodC()    {        // Do some stuff...    }}

调用者是同步的(来自控制台应用程序).让我尝试说明我尝试使用Task.WaitAll(…)和包装器任务时要做的事情:

public voID MyCallingMethod(){    List<Task> tasks = new List<Task>();    for(int c = 0 ; c < 4 ; c++)    {        MyAsyncCode asyncCode = new MyAsyncCode();        tasks.Add(Task.Run(() => asyncCode.MethodA()));    }    Task.WaitAll(tasks.ToArray());}

MethodA,MethodB和MethodC的所有行为都是在连续之前和之后在同一个线程上运行,并且在4个不同的线程上并行发生4次.换句话说,我想删除我的await调用的异步行为,因为我正在从调用者并行调用.

现在,在我进一步讨论之前,我确实理解异步代码和并行/多线程代码之间存在差异,前者并不暗示或暗示后者.我也知道实现此行为的最简单方法是删除async / await声明.不幸的是,我没有选择这样做(它在库中)并且有理由为什么我需要所有的延续都在同一个线程上(与所述库的糟糕设计有关).但更重要的是,这引起了我的兴趣,现在我想从学术角度来了解.

我试图使用PliNQ和使用.AsParallel()立即执行任务来运行它.选择(x => x.MethodA().结果).我还试图使用在这里和那里找到的AsyncHelper类,它实际上只使用.Unwrap().GetAwaiter().GetResult().我也试过其他的东西,我似乎无法得到理想的行为.我要么最终得到同一个线程上的所有调用(显然不是并行),要么以不同线程上执行的连续结束.

我正在尝试做什么,甚至是async / await和TPL太不同了(尽管两者都基于任务)?

解决方法 您调用的方法不使用ConfigureAwait(false).这意味着我们可以强制继续在我们喜欢的上下文中恢复.选项:

>安装单线程同步上下文.我相信Nito.Async有这个.
>使用自定义TaskScheduler. await查看TaskScheduler.Current并在该调度程序中恢复,如果它是非默认的.

我不确定这两种选择是否有任何利弊.选项2我认为更容易确定范围.选项2看起来像:

Task.Factory.StartNew(    () => MethodA(),new ConcurrentExclusiveSchedulerPair().ExclusiveScheduler).Unwrap();

对每个并行调用调用一次,并使用Task.WaitAll加入所有这些任务.也许你应该处理那个调度程序.

我(ab)在这里使用ConcurrentExclusiveSchedulerPair来获取单线程调度程序.

如果这些方法不是特别占用cpu的方法,则可以对所有这些方法使用相同的调度程序/线程.

总结

以上是内存溢出为你收集整理的c# – 如何并行执行嵌套的异步/等待代码,同时在等待延续中保持相​​同的线程?全部内容,希望文章能够帮你解决c# – 如何并行执行嵌套的异步/等待代码,同时在等待延续中保持相​​同的线程?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1246503.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存