2013-07-05 37 views
0

我正在做并行编程的第一步。我将CalculateSlots重写为CalculateSlotsAsync。它接缝工作正常(快3倍)。并行计算。 NET 4.0

我的问题是:它写的是否正确? 我是否需要使用最新的异步脱节模式,如果是,如何?

strategy.Slot.AsParallel() 
      .Where(slot => isCalculateAllSlots || !indicatorSlot.IsCalculated) 
      .ForAll(slot => CalculateStrategySlot(slot.SlotNumber)); 

然而,你的情况:

private void CalculateSlots(bool isCalculateAllSlots) 
{ 
    foreach (IndicatorSlot indicatorSlot in strategy.Slot) 
    { 
     if (isCalculateAllSlots || !indicatorSlot.IsCalculated) 
      CalculateStrategySlot(indicatorSlot.SlotNumber); 
    } 
} 

private void CalculateSlotsAsync(bool isCalculateAllSlots) 
{ 
    var tasks = new List<Task>(); 
    foreach (IIndicatorSlot indicatorSlot in strategy.Slot) 
    { 
     if (isCalculateAllSlots || !indicatorSlot.IsCalculated) 
     { 
      IIndicatorSlot slot = indicatorSlot; 
      Task task = Task.Factory.StartNew(() => CalculateStrategySlot(slot.SlotNumber)); 
      tasks.Add(task); 
     } 
    } 
    Task.WaitAll(tasks.ToArray()); 
} 

上i7-3630QM测试@ 2.40Gh

// Executed for 96 sec. 
for (int i = 0; i < 1000; i++) 
    CalculateSlots(true); 

// Executed for 34 sec. 
for (int i = 0; i < 1000; i++) 
    CalculateSlotsAsync(true); 
+0

代码审查不是SO的目的。代码看起来不错,但可以用(P)Linq和/或Parallel.ForEach()简化。 –

+0

我使用两年以来的SO,但仍不明白它的目的究竟是什么。我真的很害怕在这里问问题或者特别回答。在这里阅读询问在其他地方... –

+1

@MiroslavPopov:我认为Henk意味着[代码评论](http://codereview.stackexchange.com/)网站可能更适合这些类型的问题。但不要害怕提问;可能发生的最糟糕的情况是它会在没有收到任何答案的情况下关闭。 – Douglas

回答

3

对于数据的并行操作,你可以经常使用PLINQ简化您的实现,每个项目需要相对较长的时间进行计算,因此我建议将它们作为任务,但将它们标记为LongRunning(它通常具有在专用线程上执行它们的效果)呃比线程池)。

Task task = Task.Factory.StartNew(() => CalculateStrategySlot(slot.SlotNumber), 
            TaskCreationOptions.LongRunning); 

回复Task.WaitAll导致调用线程 - 在你的情况下,UI线程 - 阻塞,直到所有指定的任务已经完成。 (行为与PLINQ ForAll类似。)

为了让您的UI保持响应,您需要从阻塞方式切换到异步方式。例如,假设您有:

Task.Factory.ContinueWhenAll(tasks.ToArray(), completedTasks => 
{ 
    // callback on UI thread 
    UpdateUI(strategy.Slot); 
}, 
    CancellationToken.None, 
    TaskContinuationOptions.None, 
    TaskScheduler.FromCurrentSynchronizationContext()); 

在实践中,你还需要学习如何使用CancellationToken允许用户之前丢弃操作:

Task.WaitAll(tasks.ToArray()); 
UpdateUI(strategy.Slot); // must be called on UI thread 

你可以用这个代替它完成。

+0

谢谢@Douglas!测试了AsParalle()代码。比我的更干净。它接缝我失去了一些东西。如果它是平行的,为什么它在完全计算时阻止我的UI? –

+1

@MiroslavPopov:查看我上面的修改。 – Douglas

+0

+1谢谢@Douglas。耻辱我不能用+5投这样的建设性答案。用户必须能够正确评价一行提示和几个示例的答案。 –