技术开发 频道

直线出击!.NET 4.0并行计算深入解读

  二、 并行循环的中断和跳出

  当在进行循环时,偶尔会需要中断循环或跳出循环。下面是两种跳出循环的方法Stop和Break,LoopState是循环状态的参数。

/// <summary>
        
/// 中断Stop
        
/// </summary>
        
private void Demo5()
        {
            List
<int> data = Program.Data;
            Parallel.For(
0, data.Count, (i, LoopState) =>
            {
                
if (data[i] > 5)
                    LoopState.Stop();
                Thread.Sleep(
500);
                Console.WriteLine(data[i]);
            });
            Console.WriteLine(
"Stop执行结束。");
        }

        
/// <summary>
        
/// 中断Break
        
/// </summary>
        
private void Demo6()
        {
            List
<int> data = Program.Data;
            Parallel.ForEach(data, (i, LoopState)
=>
            {
                
if (i > 5)
                    LoopState.Break();
                Thread.Sleep(
500);
                Console.WriteLine(i);
            });
            Console.WriteLine(
"Break执行结束。");
        }

 

  执行结果如下:

并行循环的中断和跳出
 

  结论2:使用Stop会立即停止循环,使用Break会执行完毕所有符合条件的项。

  三、并行循环中为数组/集合添加项

  上面的应用场景其实并不是非常多见,毕竟只是为了遍历一个数组内的资源,我们更多的时候是为了遍历资源,找到我们所需要的。那么请继续看。

  下面是我们一般会想到的写法:

private void Demo7()
        {
            List
<int> data = new List<int>();
            Parallel.For(
0, Program.Data.Count, (i) =>
            {
                
if (Program.Data[i] % 2 == 0)
                    data.Add(Program.Data[i]);
            });
            Console.WriteLine(
"执行完成For.");
        }

        
private void Demo8()
        {
            List
<int> data = new List<int>();
            Parallel.ForEach(Program.Data, (i)
=>
            {
                
if (Program.Data[i] % 2 == 0)
                    data.Add(Program.Data[i]);
            });
            Console.WriteLine(
"执行完成ForEach.");
        }

 

  看起来应该是没有问题的,但是我们多次运行后会发现,偶尔会出现错误如下:

并行循环的中断和跳出
 

  这是因为List是非线程安全的类,我们需要使用System.Collections.Concurrent命名空间下的类型来用于并行循环体内。

说明
BlockingCollection<T>为实现 IProducerConsumerCollection<T> 的线程安全集合提供阻止和限制功能。
ConcurrentBag<T>表示对象的线程安全的无序集合。
ConcurrentDictionary<TKey, TValue>表示可由多个线程同时访问的键值对的线程安全集合。
ConcurrentQueue<T>表示线程安全的先进先出 (FIFO) 集合。
ConcurrentStack<T>表示线程安全的后进先出 (LIFO) 集合。
OrderablePartitioner<TSource>表示将一个可排序数据源拆分成多个分区的特定方式。
Partitioner提供针对数组、列表和可枚举项的常见分区策略。
Partitioner<TSource>表示将一个数据源拆分成多个分区的特定方式。

 

0
相关文章