.Net4.0 Parallel編程(三)Data Parallelism 下
在上篇文章中介紹了如何Break、Stop循環,以及如何定義線程局部變量。在本文中介紹如何在外部去取消循環、以及異常的處理。
Cancel
在并行的循環中支持通過傳遞ParallelOptions參數中的CancellationToken進行取消循環的控制,我們可以CancellationTokenSource實例化之后傳遞給ParallelOptions對象Cancellation值。下面來看個示例:
public void CancelLoop()
{
var sourceNums = Enumerable.Range(0, 1000000000);
var cts = new CancellationTokenSource();
var po = new ParallelOptions();
var stack = new ConcurrentStack<int>();
po.CancellationToken = cts.Token;
po.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
Task.Factory.StartNew(() =>
{
foreach (var num in sourceNums)
{
if (num == 1000000)
cts.Cancel();
}
});
try
{
Parallel.ForEach(sourceNums,po, num =>
{
stack.Push(num);
po.CancellationToken.ThrowIfCancellationRequested();
});
}
catch (OperationCanceledException e)
{
Console.WriteLine(e.Message);
}
Console.WriteLine(stack.Count);
}
我們來看下運行的結果:
解釋下上面的方法,并行循環的意圖是將sourceNums里面的元素推到Stack中,然后另外開啟了一個線程來控制了什么時候進行cancel操作。也許會有個疑問,為什么不是1000000呢,原因很簡單就是上面的控制的線程不可能跟下面的同時開始的,而其每次迭代運行所需要的時間也是不同的。
上面的示例中我們看的是如何終止Parallel的ForEach循環,終止For循環是一樣的,For方法中也提供了ParallelOptions參數。
Handel Exceptions
在處理并行循環的異常的與順序循環異常的處理是有所不同的,并行循環里面可能會一個異常在多個循環中出現,或則一個線程上的異常導致另外一個線程上也出現異常。比較好的處理方式就是,首先獲取所有的異常最后通過AggregateException來包裝所有的循環的異常,循環結束后進行throw。看一段示例代碼:
{
var exceptions = new ConcurrentQueue<Exception>();
Parallel.For(0, numbers.Length, i =>
{
try
{
if (numbers[i] > 10 && numbers[i] < 20)
{
throw new Exception(String.Format("numbers[{0}] betwewn 10 to 20",i));
}
}
catch (Exception e)
{
exceptions.Enqueue(e);
}
});
if (exceptions.Count > 0)
throw new AggregateException(exceptions);
}
測試方法:
public void HandleExceptions()
{
var numbers = Enumerable.Range(0, 10000).ToArray();
try
{
this.HandleNumbers(numbers);
}
catch(AggregateException exceptions)
{
foreach (var ex in exceptions.InnerExceptions)
{
Console.WriteLine(ex.Message);
}
}
}
測試結果:
對上面的方法說明下,在HandleNumbers方法中,就是一個小的demo如果元素的值出現在10-20之間就拋出異常。在上面我們的處理方法就是:在循環時通過隊列將所有的異常都集中起來,循環結束后來拋出一個AggregateException。
總結
在本文中主要說明了如何處理異常以及如何在外部取消一個并行循環。到此Task Parallel Library中的數據并行部分已經結束。下面的會就學習下,任務并行部分。