最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c# 并行和多線程編程——認(rèn)識Parallel

 更新時(shí)間:2021年02月20日 08:54:53   作者:雲(yún)霏霏  
這篇文章主要介紹了c# 并行和多線程編程的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)c# Parallel的相關(guān)知識,感興趣的朋友可以了解下

  隨著多核時(shí)代的到來,并行開發(fā)越來越展示出它的強(qiáng)大威力!使用并行程序,充分的利用系統(tǒng)資源,提高程序的性能。在.net 4.0中,微軟給我們提供了一個(gè)新的命名空間:System.Threading.Tasks。這里面有很多關(guān)于并行開發(fā)的東西,今天第一篇就介紹下最基礎(chǔ),最簡單的——認(rèn)識和使用Parallel。

一、 Parallel的使用

在Parallel下面有三個(gè)常用的方法invoke,For和ForEach。

1、Parallel.Invoke

這是最簡單,最簡潔的將串行的代碼并行化。

在這里先講一個(gè)知識點(diǎn),就是StopWatch的使用,最近有一些人說找不到StopWatch,StopWatch到底是什么東西,今天就來說明一下。

StopWatch在System.Diagnostics命名控件,要使用它就要先引用這個(gè)命名空間。

其使用方法如下:

var stopWatch = new StopWatch();   //創(chuàng)建一個(gè)Stopwatch實(shí)例

stopWatch.Start();   //開始計(jì)時(shí)

stopWatch.Stop();   //停止計(jì)時(shí)

stopWatch.Reset();  //重置StopWatch

stopWatch.Restart(); //重新啟動被停止的StopWatch

stopWatch.ElapsedMilliseconds //獲取stopWatch從開始到現(xiàn)在的時(shí)間差,單位是毫秒

本次用到的就這么多知識點(diǎn),想了解更多關(guān)于StopWatch的,去百度一下吧,網(wǎng)上有很多資料。

下面進(jìn)入整體,開始介紹Parallel.Invoke方法,廢話不多說了,首先新建一個(gè)控制臺程序,添加一個(gè)類,代碼如下:

public class ParallelDemo
 {
 private Stopwatch stopWatch = new Stopwatch();

 public void Run1()
 {
 Thread.Sleep(2000);
 Console.WriteLine("Task 1 is cost 2 sec");
 }
 public void Run2()
 {
 Thread.Sleep(3000);
 Console.WriteLine("Task 2 is cost 3 sec");
 }

 public void ParallelInvokeMethod()
 {
 stopWatch.Start();
 Parallel.Invoke(Run1, Run2);
 stopWatch.Stop();
 Console.WriteLine("Parallel run " + stopWatch.ElapsedMilliseconds + " ms.");
 
 stopWatch.Restart();
 Run1();
 Run2();
 stopWatch.Stop();
 Console.WriteLine("Normal run " + stopWatch.ElapsedMilliseconds + " ms.");
 }
}

代碼很簡單,首先新加一個(gè)類,在類中寫了兩個(gè)方法,Run1和Run2,分別等待一定時(shí)間,輸出一條信息,然后寫了一個(gè)測試方法ParallelInvokeMethod,分別用兩種方法調(diào)用Run1和Run2,然后在main方法中調(diào)用,下面來看一下運(yùn)行時(shí)間如何:

  大家應(yīng)該能夠猜到,正常調(diào)用的話應(yīng)該是5秒多,而Parallel.Invoke方法調(diào)用用了只有3秒,也就是耗時(shí)最長的那個(gè)方法,可以看出方法是并行執(zhí)行的,執(zhí)行效率提高了很多。

2、Parallel.For

這個(gè)方法和For循環(huán)的功能相似,下面就在類中添加一個(gè)方法來測試一下吧。代碼如下:

public void ParallelForMethod()
 {
 stopWatch.Start();
 for (int i = 0; i < 10000; i++)
 {
 for (int j = 0; j < 60000; j++)
 {
  int sum = 0;
  sum += i;
 }
 }
 stopWatch.Stop();
 Console.WriteLine("NormalFor run " + stopWatch.ElapsedMilliseconds + " ms.");

 stopWatch.Reset();
 stopWatch.Start();
 Parallel.For(0, 10000, item =>
 {
 for (int j = 0; j < 60000; j++)
 {
  int sum = 0;
  sum += item;
 }
 });
 stopWatch.Stop();
 Console.WriteLine("ParallelFor run " + stopWatch.ElapsedMilliseconds + " ms.");
 
 }

寫了兩個(gè)循環(huán),做了一些沒有意義的事情,目的主要是為了消耗CPU時(shí)間,同理在main方法中調(diào)用,運(yùn)行結(jié)果如下圖:

可以看到,Parallel.For所用的時(shí)間比單純的for快了1秒多,可見提升的性能是非??捎^的。那么,是不是Parallel.For在任何時(shí)候都比for要快呢?答案當(dāng)然是“不是”,要不然微軟還留著for干嘛?

下面修改一下代碼,添加一個(gè)全局變量num,代碼如下:

public void ParallelForMethod()
 {
 var obj = new Object();
 long num = 0;
 ConcurrentBag<long> bag = new ConcurrentBag<long>();

 stopWatch.Start();
 for (int i = 0; i < 10000; i++)
 {
 for (int j = 0; j < 60000; j++)
 {
  //int sum = 0;
  //sum += item;
  num++;
 }
 }
 stopWatch.Stop();
 Console.WriteLine("NormalFor run " + stopWatch.ElapsedMilliseconds + " ms.");

 stopWatch.Reset();
 stopWatch.Start();
 Parallel.For(0, 10000, item =>
 {
 for (int j = 0; j < 60000; j++)
 {
  //int sum = 0;
  //sum += item;
  lock (obj)
  {
  num++;
  }
 }
 });
 stopWatch.Stop();
 Console.WriteLine("ParallelFor run " + stopWatch.ElapsedMilliseconds + " ms.");
 
 }

Parallel.For由于是并行運(yùn)行的,所以會同時(shí)訪問全局變量num,為了得到正確的結(jié)果,要使用lock,此時(shí)來看看運(yùn)行結(jié)果:

  是不是大吃一驚啊?Parallel.For竟然用了15秒多,而for跟之前的差不多。這主要是由于并行同時(shí)訪問全局變量,會出現(xiàn)資源爭奪,大多數(shù)時(shí)間消耗在了資源等待上面。

一直說并行,那么從哪里可以看出來Parallel.For是并行執(zhí)行的呢?下面來寫個(gè)測試代碼:

Parallel.For(0, 100, i =>
 {
 Console.Write(i + "\t");
 });

從0輸出到99,運(yùn)行后會發(fā)現(xiàn)輸出的順序不對,用for順序肯定是對的,并行同時(shí)執(zhí)行,所以會出現(xiàn)輸出順序不同的情況。

3、Parallel.Foreach

這個(gè)方法跟Foreach方法很相似,想具體了解的,可以百度些資料看看,這里就不多說了,下面給出其使用方法:

List<int> list = new List<int>();
 list.Add(0);
 Parallel.ForEach(list, item =>
 {
 DoWork(item);
 });

二、 Parallel中途退出循環(huán)和異常處理

1、當(dāng)我們使用到Parallel,必然是處理一些比較耗時(shí)的操作,當(dāng)然也很耗CPU和內(nèi)存,如果我們中途向停止,怎么辦呢?

在串行代碼中我們break一下就搞定了,但是并行就不是這么簡單了,不過沒關(guān)系,在并行循環(huán)的委托參數(shù)中提供了一個(gè)ParallelLoopState,

該實(shí)例提供了Break和Stop方法來幫我們實(shí)現(xiàn)。

Break: 當(dāng)然這個(gè)是通知并行計(jì)算盡快的退出循環(huán),比如并行計(jì)算正在迭代100,那么break后程序還會迭代所有小于100的。

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

下面來寫一段代碼測試一下:

public void ParallelBreak()
 {
 ConcurrentBag<int> bag = new ConcurrentBag<int>();
 stopWatch.Start();
 Parallel.For(0, 1000, (i, state) =>
 {
 if (bag.Count == 300)
 {
  state.Stop();
  return;
 }
 bag.Add(i);
 });
 stopWatch.Stop();
 Console.WriteLine("Bag count is " + bag.Count + ", " + stopWatch.ElapsedMilliseconds);
 }

這里使用的是Stop,當(dāng)數(shù)量達(dá)到300個(gè)時(shí),會立刻停止;可以看到結(jié)果"Bag count is 300",如果用break,可能結(jié)果是300多個(gè)或者300個(gè),大家可以測試一下。

2、異常處理

  首先任務(wù)是并行計(jì)算的,處理過程中可能會產(chǎn)生n多的異常,那么如何來獲取到這些異常呢?普通的Exception并不能獲取到異常,然而為并行誕生的AggregateExcepation就可以獲取到一組異常。

這里我們修改Parallel.Invoke的代碼,修改后代碼如下:

public class ParallelDemo
 {
 private Stopwatch stopWatch = new Stopwatch();

 public void Run1()
 {
 Thread.Sleep(2000);
 Console.WriteLine("Task 1 is cost 2 sec");
 throw new Exception("Exception in task 1");
 }
 public void Run2()
 {
 Thread.Sleep(3000);
 Console.WriteLine("Task 2 is cost 3 sec");
 throw new Exception("Exception in task 2");
 }

 public void ParallelInvokeMethod()
 {
 stopWatch.Start();
 try
 {
 Parallel.Invoke(Run1, Run2);
 }
 catch (AggregateException aex)
 {
 foreach (var ex in aex.InnerExceptions)
 {
  Console.WriteLine(ex.Message);
 }
 }
 stopWatch.Stop();
 Console.WriteLine("Parallel run " + stopWatch.ElapsedMilliseconds + " ms.");

 stopWatch.Reset();
 stopWatch.Start();
 try
 {
 Run1();
 Run2();
 }
 catch(Exception ex)
 {
 Console.WriteLine(ex.Message);
 }
 stopWatch.Stop();
 Console.WriteLine("Normal run " + stopWatch.ElapsedMilliseconds + " ms.");
 }
}

順序調(diào)用方法我把異常處理寫一起了,這樣只能捕獲Run1的異常信息,大家可以分開寫。捕獲AggregateException 異常后,用foreach循環(huán)遍歷輸出異常信息,可以看到兩個(gè)異常信息都顯示了。

點(diǎn)擊這里,下載源碼

以上就是c# 并行和多線程編程——認(rèn)識Parallel的詳細(xì)內(nèi)容,更多關(guān)于c# 并行和多線程編程的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#中ManualResetEvent用法詳解

    C#中ManualResetEvent用法詳解

    這篇文章主要為大家詳細(xì)介紹了C#中ManualResetEvent用法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • C#中Task.ContinueWith連續(xù)任務(wù)使用實(shí)例

    C#中Task.ContinueWith連續(xù)任務(wù)使用實(shí)例

    本文主要介紹了C#中Task.ContinueWith連續(xù)任務(wù)使用實(shí)例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C#中哈希表(Hashtable)的介紹及簡單用法

    C#中哈希表(Hashtable)的介紹及簡單用法

    在.NET Framework中,Hashtable是System.Collections命名空間提供的一個(gè)容器,用于處理和表現(xiàn)類似key/value的鍵值對
    2013-03-03
  • 詳解C#讀寫Excel的幾種方法

    詳解C#讀寫Excel的幾種方法

    這篇文章主要介紹了詳解C#讀寫Excel的幾種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • c# Base關(guān)鍵字的使用

    c# Base關(guān)鍵字的使用

    c# Base關(guān)鍵字的使用示例代碼,大家可以參考下用法。
    2009-07-07
  • C# WPF如何反射加載Geometry幾何圖形數(shù)據(jù)圖標(biāo)

    C# WPF如何反射加載Geometry幾何圖形數(shù)據(jù)圖標(biāo)

    這篇文章主要介紹了C# WPF如何反射加載Geometry幾何圖形數(shù)據(jù)圖標(biāo),幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-03-03
  • C# 快速高效率復(fù)制對象(表達(dá)式樹)

    C# 快速高效率復(fù)制對象(表達(dá)式樹)

    在代碼中經(jīng)常會遇到需要把對象復(fù)制一遍,或者把屬性名相同的值復(fù)制一遍。本文將對其解決方法進(jìn)行詳細(xì)介紹。下面跟著小編一起來看下吧
    2017-04-04
  • C# Winform窗口之間傳值的多種方法淺析

    C# Winform窗口之間傳值的多種方法淺析

    這篇文章主要介紹了C# Winform窗口之間傳值的多種方法淺析,本文起講解了通過構(gòu)造器傳值、通過屬性傳遞、通過事件攜帶參數(shù)傳遞等方法,需要的朋友可以參考下
    2015-04-04
  • C#使用selenium實(shí)現(xiàn)操作瀏覽器并且截圖

    C#使用selenium實(shí)現(xiàn)操作瀏覽器并且截圖

    這篇文章主要為大家詳細(xì)介紹了C#如何使用selenium組件實(shí)現(xiàn)操作瀏覽器并且截圖,文中的示例代碼簡潔易懂,有需要的小伙伴可以參考一下
    2024-01-01
  • C#實(shí)現(xiàn)在Excel中插入和操作切片器

    C#實(shí)現(xiàn)在Excel中插入和操作切片器

    本文主要介紹了如何使用C#在Excel中插入和操作切片器,包括插入切片器到透視表和表格,修改切片器屬性以及刪除切片器,主要使用了Spire.XLSfor.NET庫來實(shí)現(xiàn)這些功能,需要的朋友可以參考下
    2025-03-03

最新評論

扶风县| 德庆县| 泰兴市| 沁源县| 修水县| 盐池县| 广州市| 昭平县| 梓潼县| 城口县| 朝阳市| 包头市| 巴马| 盘山县| 久治县| 都安| 宁安市| 富源县| 府谷县| 嵊泗县| 明溪县| 嘉荫县| 黄陵县| 隆安县| 中超| 正宁县| 十堰市| 蓝田县| 卢湾区| 凤山市| 汤阴县| 仁化县| 曲松县| 正定县| 宁波市| 赫章县| 甘泉县| 南乐县| 信宜市| 陆川县| 来凤县|