[C#] 並行編程Parallel

来源:http://www.cnblogs.com/jinxin201211/archive/2017/02/20/6418900.html
-Advertisement-
Play Games

一、Parallel的使用 在Parallel下麵有三個常用的方法Invoke、For和ForEach。 1、Parallel.Invoke 執行Parallel.ParallelInvokeMethod()的結果: 可以看出正常調用Run1()和Run2()所花費的時間在5秒左右,而用Parall ...


一、Parallel的使用

在Parallel下麵有三個常用的方法Invoke、For和ForEach。

1、Parallel.Invoke

 1 public class ParallelDemo
 2 {
 3     private Stopwatch stopWatch = new Stopwatch();
 4 
 5     public void Run1()
 6     {
 7         Thread.Sleep(2000);
 8         Console.WriteLine("Task 1 is cost 2 sec");
 9     }
10     public void Run2()
11     {
12         Thread.Sleep(3000);
13         Console.WriteLine("Task 2 is cost 3 sec");
14     }
15 
16     public void ParallelInvokeMethod()
17     {
18         stopWatch.Start();
19         Parallel.Invoke(Run1, Run2);
20         stopWatch.Stop();
21         Console.WriteLine("Parallel run " + stopWatch.ElapsedMilliseconds + " ms.");
22 
23         stopWatch.Restart();
24         Run1();
25         Run2();
26         stopWatch.Stop();
27         Console.WriteLine("Normal run " + stopWatch.ElapsedMilliseconds + " ms.");
28     }
29 }                

執行Parallel.ParallelInvokeMethod()的結果:

可以看出正常調用Run1()和Run2()所花費的時間在5秒左右,而用Parallel.Invoke方法調用值用了3秒左右,也就是耗時最長的那個方法所花費的時間。

2、Parallel.For

這個方法和For迴圈類似。在ParallelDemo類中添加一個ParallelForMethod()方法:

 1 public void ParallelForMethod()
 2         {
 3             stopWatch.Start();
 4             for (int i = 0; i < 10000; i++)
 5             {
 6                 for (int j = 0; j < 60000; j++)
 7                 {
 8                 }
 9             }
10             stopWatch.Stop();
11             Console.WriteLine("NormalFor run " + stopWatch.ElapsedMilliseconds + " ms.");
12 
13             stopWatch.Reset();
14             stopWatch.Start();
15             Parallel.For(0, 10000, item =>
16             {
17                 for (int j = 0; j < 60000; j++)
18                 {
19                 }
20             });
21             stopWatch.Stop();
22             Console.WriteLine("ParallelFor run " + stopWatch.ElapsedMilliseconds + " ms.");
23 
24         }

運行結果:

這個例子中Parallel.For比for耗費的時間要少,但是Parallel.For並不總是比for快。例如:

 1             long sum = 0;
 2             stopWatch.Start();
 3             for (int i = 0; i < 10000; i++)
 4             {
 5                 for (int j = 0; j < 60000; j++)
 6                 {
 7                     sum++;
 8                 }
 9             }
10             stopWatch.Stop();
11             Console.WriteLine("NormalFor run " + stopWatch.ElapsedMilliseconds + " ms.");
12 
13             stopWatch.Reset();
14             stopWatch.Start();
15             Parallel.For(0, 10000, item =>
16             {
17                 for (int j = 0; j < 60000; j++)
18                 {
19                     sum++;
20                 }
21             });
22             stopWatch.Stop();
23             Console.WriteLine("ParallelFor run " + stopWatch.ElapsedMilliseconds + " ms.");

 用Parallel.For所耗費的時間反而更多,是for的3倍以上,這是因為Parallel.For是並行運行的,所以會同時訪問sum,會出現資源爭奪,耗費大量的時間在資源等待上面。

3、Parallel.ForEach

Parallel.ForEach與foreach類似

 1         public void ParallelForEachMethod()
 2         {
 3             int[] nums = new int[100];
 4             for (int i = 0; i < 100; i++)
 5             {
 6                 nums[i] = i;
 7             }
 8             stopWatch.Start();
 9             foreach (var item in nums)
10             {
11                 Console.Write(item + "\t");
12             }
13             stopWatch.Stop();
14             Console.WriteLine("\nNormalFor run " + stopWatch.ElapsedMilliseconds + " ms.");
15 
16             stopWatch.Reset();
17             stopWatch.Start();
18             Parallel.ForEach(nums, item =>
19             {
20                 Console.Write(item + "\t");
21             });
22             stopWatch.Stop();
23             Console.WriteLine("\nParallelFor run " + stopWatch.ElapsedMilliseconds + " ms.");
24         }

從0到99輸出,從運行結果可以看出,Parallel.ForEach的輸出順序是不定的,而foreach是按順序輸出。

 

二、Parallel中途退出和異常處理

1、在串列操作中,使用break語句即可退出迴圈,但是再並行操作中,就不是這麼回事了。並行迴圈的委托參數中含有一個ParallelLoopState,該實例擁有Break()和Stop()這兩個方法,可以用來退出並行迴圈。

Break:當然這個是通知並行計算儘快的退出迴圈,比如並行計算正在迭代100,那麼break後程式還會迭代所有小於100的。

Stop:這個就不一樣了,比如正在迭代100突然遇到stop,那它啥也不管了,直接退出。

下麵一段代碼測試:

 1         public void ParallelBreak()
 2         {
 3             ConcurrentBag<int> bag = new ConcurrentBag<int>();
 4             Stopwatch stopWatch = new Stopwatch();
 5             stopWatch.Start();
 6             Parallel.For(0, 1000, new ParallelOptions { MaxDegreeOfParallelism = 1 }, (i, state) =>
 7             {
 8                 if (bag.Count == 300)
 9                 {
10                     state.Stop();
11                     return;
12                 }
13                 bag.Add(i);
14             });
15             stopWatch.Stop();
16             Console.WriteLine("Bag count is " + bag.Count + ", " + stopWatch.ElapsedMilliseconds);
17         }

當Parallel.For迴圈遍歷了300個元素時,就運行Stop()方法退出迴圈。

2、異常處理

 1         public void Run1()
 2         {
 3             Thread.Sleep(2000);
 4             Console.WriteLine("Task 1 is cost 2 sec");
 5             throw new Exception("Exception in task 1");
 6         }
 7         public void Run2()
 8         {
 9             Thread.Sleep(3000);
10             Console.WriteLine("Task 2 is cost 3 sec");
11             throw new Exception("Exception in task 2");
12         }
13         public void Run3()
14         {
15             Thread.Sleep(5000);
16             Console.WriteLine("Task 3 is cost 5 sec");
17             throw new Exception("Exception in task 3");
18         }
19 
20         public void ParallelInvokeMethod()
21         {
22             stopWatch.Start();
23             try
24             {
25                 Parallel.Invoke(Run1, Run2, Run3);
26             }
27             catch (AggregateException ex)
28             {
29                 foreach (var item in ex.InnerExceptions)
30                 {
31                     Console.WriteLine(item.Message);
32                 }
33             }
34             stopWatch.Stop();
35             Console.WriteLine("Parallel run " + stopWatch.ElapsedMilliseconds + " ms.");
36 
37             stopWatch.Restart();
38             try
39             {
40                 Run1();
41                 Run2();
42                 Run3();
43             }
44             catch (Exception ex)
45             {
46                 Console.WriteLine(ex.Message);
47             }
48             stopWatch.Stop();
49             Console.WriteLine("Normal run " + stopWatch.ElapsedMilliseconds + " ms.");
50         }

Parallel.Invoke中捕捉每個方法的異常,串列方法能捕捉到Run1的異常。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1,關於欄位不匹配時候想要具體看哪個欄位DbEntityValidationException 類。 2,一般我們傳特殊符號時候自動編碼轉移System.Web.HttpUtility.UrlDecode(model.selgrade)。 ...
  • 1、鏈接例子: string url = "http://domainName:port/1/2/3/4.htm?sysCode=1001020&token=QXJzemR3YXlWdm9YMFhneFU0c2tqSXp6YmJqMVNQSUVlWndEbm9yellBNHp5SXBmK2gxVGx ...
  • 新建的mvc4 項目,然後從其他項目里拷貝shared文件夾和_ViewStart.cshtml文件過去,然後在@符號上出現“沒有為擴展名“.cshtml”註冊的生成提供程式” ...
  • 這是在Rudy Huyn的blog上看到的, "Status" 是在win10上才出現的屬性, 用來區分系統還是挺有效的。 ...
  • 目錄 1. 字元串 1.1. 字元串中的轉義序列 1.2. 字元串的不可變性 1.3. 字元串索引 1.4. 字元串分割:split 1.5. 數組連接成字元串:join 2. 數組 2.1. 數組索引 2.2. 多維數組 2.3. 數組方法 2.3.1. 數據追加到數組的尾部push() 函數 2 ...
  • 首先獲取微信簽名,Controller代碼: public ActionResult MutualHelpAdd() { var jssdkUiPackage = JSSDKHelper.GetJsSdkUiPackage(WeChatParameter._appID, WeChatParamete ...
  • 您在使用站點監控時,返回的6XX狀態碼均為雲監控自定義HTTP狀態碼,具體含義如下表所示: 狀態碼 HTTP常見狀態碼說明如下,可按ctrl+F快速查找: ...
  • 文檔目錄 本節內容: 簡介 安裝 創建工作 調度工作 更多 簡介 Quartz 是一個功能完整的開源工作調度系統,可用於最小的應用到一個大型的企業系統.Abp.Quartz 包簡單地把Quartz集成到ABP中. ABP已經內置後持久化的台作業和工作者,如果你有更高的調度上的需求,Quzrtz是一個 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...