多核時代 .NET Framework 4 中的並行程式設計5---並行迴圈Parallel Loop

weixin_33766168發表於2017-11-09

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物件.



    本文轉自風車車  部落格園部落格,原文連結:http://www.cnblogs.com/xray2005/archive/2011/08/30/2159052.html,如需轉載請自行聯絡原作者




相關文章