2017-07-28 22 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存在瓶頸並實際訪問相同的阻止資源。但是,如果這種方法是有效的,那麼我的答案也應該是有效的。 –