如何在并行foreach中使用await?

Thu*_*3eR 7 c# console-application pim async-await parallel.foreach

因此,我试图解决这个问题,这是我晚上最好的部分.

我很幸运昨天被介绍到了parallel.foreach,它的工作方式就像我想要的那样,除了一个细节.

我有以下内容:

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

        });
Run Code Online (Sandbox Code Playgroud)

在方法"MyMethod"中我有很多逻辑可以完成并且大部分都很好但我在api调用我获取数据的地方我使用异步任务为了能够使用"await"以便代码等到直到特定部分被执行然后继续:

    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
        }
    }
Run Code Online (Sandbox Code Playgroud)

问题:

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

2第二个问题是我在许多api调用中得到"任务被取消"

3如上所述,代码不会等待每个方法完全执行.

在继续下一步之前,我无法让它在ExecuteMeasurmentAndChartLogic()方法中执行所有操作.

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

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

侧面注意:我知道装箱物品并在所有数据出现之前添加到数据库中并不是最佳实践,但我正在整合PIM并且过程很简单

我想要运行几个线程但同时我希望在继续下一个方法之前为每个项执行fuill逻辑.

澄清:

几个项目正在运行

在继续下一部分代码之前,每个项目都需要handel 所需的所有逻辑,并且等待着这样做.

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

而不是我使用的Parallel.ForEach:

    Task task1 = Task.Factory.StartNew(() => MyMethod(data, measurements));
    Task.WaitAll(task1);
Run Code Online (Sandbox Code Playgroud)

但这不是一个很大的帮助

相当新的,并没有能够理解我在做错的地方.

编辑:更新了这个问题

编辑:这是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);
        }

    }
Run Code Online (Sandbox Code Playgroud)

编辑:背景:我打电话给api获取大量数据.对于此数据中的每个项目,我需要进行api调用并获取我应用于该项目的数据.

读完评论之后,这些评论让我以不同的方式思考.我可以遍历我的所有项目并为它们做一些小逻辑,并在任务列表中添加一个url并创建一个单独执行此任务的任务.

请保持更新

Edu*_*ner 14

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

Task.WaitAll(data.Select(d => MyMethod(d, someParam)).ToArray());
Run Code Online (Sandbox Code Playgroud)

  • @ Ra3IDeN那么你的实际方法不是为了并行运行而设计的,你需要修复*那个*. (3认同)
  • @ Ra3IDeN答案*减少*可以并行完成的工作量,对于正在进行的主要工作,*错误*并行化并行化不能并行完成的工作,导致不安全的代码. (2认同)