2012-05-18 62 views
1

在过去,我通过使用PLINQ可以轻松地将for循环变成一个多任务速度的恶魔。如何异步处理集合集合?

但是,由于处理了一系列集合,我的时间更加困难。

我可能会自己想出来,但我认为看看其他人如何解决这个问题也是有用的。

更新:我相信有下面我的代码的概念问题,但我已经无法用语言表达完全是。如果任何人都可以看到我说的,伟大的,但我会考虑这个越来越尽量使问题更好的整体(或删除它,如果我意识到这是完全我的错)

这里的主要逻辑:

public static void Execute() 
    { 
     var service = Locator.Get<ICakeService>(); 
     using (var db = new Cake.Model.CakeContainer()) 
     { 
      foreach (var campaigns in service.ExportCampaigns()) 
      { 
       // --> THIS LOOP SHOULD BE EXECUTED IN A SEPARATE THREAD 
       foreach (var campaign in campaigns) 
       { 
        // ... logic to process a campaign ... 
       } 
      } 
     } 
    } 

这里的服务:

public IEnumerable<campaign[]> ExportCampaigns() 
    { 
     campaign[] result = null; 
     var service = new exportSoapClient("exportSoap"); 
     // --> IF I DO A PARALLEL FOREACH HERE THE CLIENT CODE ABOVE 
     // STOPS MAKING SENSE TO ME... 
     foreach (var offer in this.ExportOffers()) 
     { 
      var response = service.Campaigns(
           api_key: this.apiKey, 
           offer_id: offer.offer_id); 
      yield return result; 
     } 
    } 
+0

什么是你的问题的一个版本? –

+0

我刚换了标题 –

+0

“绊脚石”是什么意思? –

回答

2

进行并行化的另一个选择是

Parallel.Foreach(service.ExportCampaigns(), campaigns => 
{ 
    // --> THIS LOOP will be run in multiple threads at the same time 


    foreach (var campaign in campaigns) 
    { 
     // ... logic to process a campaign ... 
    } 
}); 

如果内foreach有太少的工作要做到这一点可能比esskar's solution一个更好的选择。

这里是没有lambadas

public static void Execute(Action<campaign[]> action) 
{ 
    var service = Locator.Get<ICakeService>(); 
    using (var db = new Cake.Model.CakeContainer()) 
    { 
     Parallel.Foreach(service.ExportCampaigns(), action); 
    } 
} 

//This method will be executed in parallel for each element in the IEnumerable<campaign[]>. 
private void ProcessCampaigns(campaign[] campaigns) 
{ 
    foreach (var campaign in campaigns) 
    { 
     // ... logic to process a campaign ... 
    } 
} 

// Call to Execute looks something like this: 
command.Execute(ProcessCampaigns) 
+0

,如果我想,我可以发送ProcessCampaigns lambda作为参数执行,所以'执行(动作行动)',对吧? –

+0

这是正确的,您只需将'Action'而不是'ProcessCampaigns'传递给该方法。 –

+0

是的,这是我需要实现的点,使其工作,谢谢 –

0

使用Parallel助手从System.Threading.Task

Parallel.Foreach(campaigns, compaign => 
{ 
    // ... logic to process a campaign ... 
}); 

编辑:下面一个完整的例子

public static void Execute() 
{ 
    var service = Locator.Get<ICakeService>(); 
    using (var db = new Cake.Model.CakeContainer()) 
    { 
     foreach (var campaigns in service.ExportCampaigns()) 
     { 
      ProcessCampaigns(campaigns);     
     } 
    } 
} 

private void ProcessCampaigns(IEnumerable<Campaign>> campaigns) 
{ 
    Parallel.Foreach(compaigns, ProcessCampaign); 
} 

private void ProcessCampaign(Campaign campaign) 
{ 
    // ... logic to process a campaign ... 
} 
+1

可能需要在这里分配一个本地实例的“活动”或“活动”,因为lambda执行可能会击中foreach循环中的最后/重用值。 –

+0

我不知道在哪里把并行foreach循环放在我的发布代码中... mabye我错过了一些明显的东西 - 我会重新检查它 –