2013-07-05 60 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投這樣的建設性答案。用戶必須能夠正確評價一行提示和幾個示例的答案。 –