多核时代 .NET Framework 4 中的并行编程5---并行循环Parallel Loop

1. 并行循环与顺序循环区别

首先,来运行下面的代码,查看区别,代码如下:

static void Main(string[] args)

        {

            Console.WriteLine("使用For循环");

 

            for (int i = 0; i <= 10; i++)

            {

                Console.WriteLine("i = {0}, 线程id = {1}",

                    i, Thread.CurrentThread.ManagedThreadId);

                Thread.Sleep(10);

            }

 

            Console.WriteLine("使用Parallel.For");

 

            Parallel.For(0, 10, i =>

            {

                Console.WriteLine("i = {0}, 线程id = {1}", i,

                Thread.CurrentThread.ManagedThreadId);

                Thread.Sleep(10);

            });

 

            Console.ReadLine();

        }

最终运行的效果如下图所示:

 

从上面的代码运行效果图来我们可以看到,只有一个线程在处理for循环.而Parallel.For的循环,则会有多个线程进行处理,从而在某种程度改善了程序代码的运行效率.他们的区别就不言而喻.

2. Parallel的并行循环的几种方法

Parallel类提供以下几种并行执行循环的方法(他们还有很多其他的重载方法)。具体说明如下:

Ø Parallel.For:执行 for 循环,其中可能会并行运行迭代.

Ø Parallel.ForEach: 对某种集合中的对象执行 foreach,其中可能会并行运行迭代,需要主要的是,它不保证按照集合的索引顺序去执行迭代。

Ø Parallel.Invoke:尽可能并行执行提供的每个操作.

示例代码如下:

private static void Invoke()

        {

            Action[] actions = new Action[5];

            actions[0] = new Action(() =>

             {

                 Console.WriteLine("thread id={0}", Thread.CurrentThread.ManagedThreadId);

             });

            actions[1] = new Action(() =>

            {

                Console.WriteLine("thread id={0}", Thread.CurrentThread.ManagedThreadId);

            });

            actions[2] = new Action(() =>

            {

                Console.WriteLine("thread id={0}", Thread.CurrentThread.ManagedThreadId);

            });

            actions[3] = new Action(() =>

            {

                Console.WriteLine("thread id={0}", Thread.CurrentThread.ManagedThreadId);

            });

            actions[4] = new Action(() =>

            {

                Console.WriteLine("thread id={0}", Thread.CurrentThread.ManagedThreadId);

            });

 

            Parallel.Invoke(actions);

          

 

            List<int> list = new List<int>() { 1, 2, 3, 4, 5, 6 };

 

            Parallel.ForEach(list, i =>

            {

                Console.WriteLine("i={0},thread id={1}", i, Thread.CurrentThread.ManagedThreadId);

            });

 

            Console.ReadLine();

        }

3. 返回值

ParallelLoopResult提供执行 Parallel 循环的完成状态。其中, ParallelLoopResult有两个属性:

Ø IsCompleted 获取该循环是否已运行完成(即,该循环的所有迭代均已执行,并且该循环没有收到提前结束的请求)。 

Ø LowestBreakIteration 获取从中调用 Break 的最低迭代的索引。

代码如下:

ParallelLoopResult loopResult = Parallel.ForEach(list, (int i, ParallelLoopState state) =>

             {

                 if (i == 5)

                 {

                     state.Break();

                 }

                 Console.WriteLine("i={0},thread id={1}", i, Thread.CurrentThread.ManagedThreadId);

             });

 

            Console.WriteLine("IsCompleted: {0}", loopResult.IsCompleted);

            Console.WriteLine("BreakValue: {0}", loopResult.LowestBreakIteration.HasValue);

            Console.ReadLine();

 

4. 控制循环

ParallelOptions类存储用于配置 Parallel 类的方法的操作的选项。其属性有:

Ø CancellationToken 获取或设置与此 ParallelOptions 实例关联的 CancellationToken。 

Ø MaxDegreeOfParallelism 获取或设置此 ParallelOptions 实例所允许的最大并行度。 

Ø TaskScheduler 获取或设置与此 ParallelOptions 实例关联的 TaskScheduler。 将此属性设置为 null,以指示应使用当前计划程序。

如下代码,通过设置CancellationToken以便可以取消Parallel的循环:

CancellationTokenSource token = new CancellationTokenSource();

            Task.Factory.StartNew(() =>

            {

                Thread.Sleep(5000);

                token.Cancel();

                Console.WriteLine("Token Cancelled.");

 

            });

            ParallelOptions loopOptions = new ParallelOptions()

            {

                CancellationToken = token.Token,

                MaxDegreeOfParallelism = 2

 

            };

            try

            {

               

                Parallel.For(0, Int64.MaxValue, loopOptions, i =>

                {

                  

                    Console.WriteLine("i={0},thread id={1}", i, Thread.CurrentThread.ManagedThreadId);

                    Thread.Sleep(1000);

                });

            }

            catch (OperationCanceledException)

            {

                Console.WriteLine("Exception...");

            }

其中, MaxDegreeOfParallelism设置为2,表示最多可以有2个并行量(可以理解成并行线程数目),如果设置为为 -1,表示对于应该使用的并行量没有上限设置。如果将其设置为1,则效果和单线程一样.

5. 停止/中断循环

通过调用ParallelLoopState实例的Stop方法和Break方法,可以停止和中断当前循环的执行.其中,

Ø Break 告知 Parallel 循环应在系统方便的时候尽早停止执行当前迭代之外的迭代.

Ø Stop 告知 Parallel 循环应在系统方便的时候尽早停止执行。

代码如下:

 Parallel.ForEach(list, (int i, ParallelLoopState state) =>

            {

                if (i == 5)

                {

                    state.Break();

                }

               

                Console.WriteLine("i={0},thread id={1}", i, Thread.CurrentThread.ManagedThreadId);

            });

其中, ParallelLoopState类的实例由Parallel类自动创建并传递到所执行的方法中.所以我们可以直接使用,而不是需要事前申明并实例一个ParallelLoopState对象.

posted @ 2011-08-30 01:30 ♂风车车 阅读(...) 评论(...) 编辑 收藏