如何在并行foreach中使用await?

图恩3eR

因此,我将大部分时间都花在想尽办法上。

昨天我很幸运地被介绍给parallel.foreach,它的工作方式就像我想要的一样,只是从一个细节开始。

我有以下内容:

        Parallel.ForEach(data, (d) =>
        {
            try
            {
                MyMethod(d, measurements);
            }
            catch (Exception e)
            {
              // logg
            }

        });

在方法“ MyMethod”中,我有很多逻辑可以完成,并且大多数情况都很好,但是我在获取数据的地方进行了api调用,为此我使用了异步任务,以便能够使用“等待”来使代码等到特定部分执行完毕,然后继续:

    private async void MyMethod(PimData pimData, IEnumerable<ProductMeasurements> measurements)
    {
        try
        {
           // alot of logic but most relevant part 

            await Task.WhenAll(ExecuteMeasurmentAndChartLogic(pimData.ProductNumber, entity));
            await Task.WhenAll(resourceImportManager.HandleEntityImageFiles(pimData.ProductType + pimData.ProductSize,SwepImageType.Png, ResourceFileTypes.ThreeD, entity, LinkTypeId.ProductResource));

            await Task.WhenAll(resourceImportManager.HandleEntityImageFiles(pimData.ProductSketch, SwepImageType.Png, ResourceFileTypes.Sketch, entity, LinkTypeId.ProductResource));

        }
        catch (Exception e)
        {
            // logg
        }
    }

问题

1对于初学者,循环在所有代码完成之前完成

2第二个问题是我在很多api调用中都收到“任务已取消”

3第三,如上所述,代码不等待每个方法完全执行。

在前进到下一步之前,我无法获取它执行ExecuteMeasurmentAndChartLogic()方法中的所有内容。

这给了我以下问题(更多问题):

在这种方法中,我创建了一个项目并将其添加到数据库中,并且该项目需要我从ExecuteMeasurmentAndChartLogic()内部完成的api调用中获取的更多信息,但问题是一些项目变得残酷并且不得不等待其余的数据不是我想要的。

旁注:我知道在所有数据都存在之前先创建项目并添加到db中并不是最佳实践,但是我正在集成到PIM中,并且此过程很精细

我希望运行多个线程,但同时我希望在继续执行下一个方法之前为每个项目执行fuill逻辑。

澄清:

几项正在运行

每个项目都会处理它需要处理的所有逻辑,然后再继续进行代码的下一部分,通常应等待。

在上面的代码中,在ExecuteMeasurmentAndChartLogic()完成之前执行resourceImportManager()方法。这是我不想要的。

我用的不是Parallel.ForEach:

    Task task1 = Task.Factory.StartNew(() => MyMethod(data, measurements));
    Task.WaitAll(task1);

但这并没有多大帮助

对此还算陌生,还没有办法了解我在哪里做错了。

编辑:与此有关的问题

编辑:这是ExecuteMeasurmentAndChartLogic()的样子:

    public async Task ExecuteMeasurmentAndChartLogic(string productNumber, Entity entity)
    {
        try
        {
            GrafGeneratorManager grafManager = new GrafGeneratorManager();
            var graphMeasurmentList = await MeasurmentHandler.GetMeasurments(productNumber);

            if (graphMeasurmentList.Count == 0) return;

            var chart = await grafManager.GenerateChart(500, 950, SystemColors.Window, ChartColorPalette.EarthTones,
                "legend", graphMeasurmentList);

            await AddChartsAndAddToXpc(chart, entity, productNumber);
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }

    }

编辑:对此的背景:我对api进行调用以获取大量数据。对于此数据中的每个项目,我需要进行api调用并获取适用于该项目的数据。

在阅读了alos的评论后,我开始以不同的方式思考。我也许可以遍历我所有的项目,并对它们做些次要的逻辑,然后在任务列表中添加一个url,并创建一个单独的任务来逐个执行该任务。

将保持此更新

爱德华·勒普纳

完全不使用Parralel.ForEach使您的方法返回Task而不是void,收集所有任务并等待它们,例如:

Task.WaitAll(data.Select(d => MyMethod(d, someParam)).ToArray());

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章