2017-07-28 23 views
5

所以我试图找出这一点的夜晚的更好的一部分。如何在平行的foreach中使用await?

我很幸运,昨天介绍了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()方法 前进到下一个步骤之前执行的一切。

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

在这种方法中,我创建一个项目,并把它添加到数据库,而这个项目需要更多的信息,我从被内部完成API调用得到ExecuteMeasurmentAndChartLogic()的问题,但问题是有几个项目被揪出来,必须等待其他数据不符合我的要求。

侧面说明:我所知道的是装箱的物品后,加入到数据库之前,所有的数据都是没有最好的做法,但我对PIM集成和这个过程是微妙

我想要运行几个线程,但同时我想在执行下一个方法之前为每个项目执行fuill逻辑。

澄清:

几个项目运行

每个项目HANDELS ALL它需要在移动到代码的下一部分之前韩德尔的逻辑,noramly用的await做到这一点。

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

而不是平行。的foreach我用:

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

但wasnt太大的帮助

相当新的这一点,还没有能够明白的地方我做错了。

编辑: 更新的问题与此

编辑:这是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调用并获取适用于该项目的数据。

阅读评论这阿洛斯让我思考的向度方式后。我也许可以遍历所有的项目并为它们做一些次要的逻辑,并在任务列表中添加一个url,并制作一个一个一个地执行这个任务的单独任务。

将保持这种更新

+0

一旦处理完成,使用回调委托。 – Ramankingdom

+0

为什么'MyMethod'是'async void'而不是'async Task'的任何特殊原因? – GWigWam

+0

@GWigWam没有特别的理由,是意去改变它,谢谢你提醒我 – ThunD3eR

回答

7

不要使用Parralel.ForEach可言。让你的方法返回任务而不是无效,收集所有的任务,并等待它们:

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

此分享想法确实给了我一个更好的结果,但我担心,它是否实际上同时执行每个项目的逻辑?似乎要比循环更慢慢我开始 – ThunD3eR

+0

我看到这是每个项目得到一个任务,但项目二等待项目一要执行,这不是我想要的,让我回到正常的foreach循环 – ThunD3eR

+0

我提供的代码是异步和并行。如果线程池配置中断或线程不足以捕获,它可能会在一个线程中执行。或者,也许MyMethod存在瓶颈并实际访问相同的阻止资源。但是,如果这种方法是有效的,那么我的答案也应该是有效的。 –