日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

.Net 4.0并行库实用性演练

發布時間:2024/4/14 asp.net 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .Net 4.0并行库实用性演练 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  前面說在練習Parallel時,發現另有乾坤,是這樣的代碼:

代碼 static IEnumerable<Person> testFill()
{
var list
=new List<Person>(9);

Enumerable.Range(
1, 99999).ToList().ForEach(n =>
{
var name
="Person"+ n %9;
list.Add(
new Person { Id = n, Name = name });
});
Console.WriteLine(
"Person's count is {0}", list.Count);
return list;
}

static IEnumerable<Person> testFillParallel()
{
var list
=new List<Person>(9);

Enumerable.Range(
1, 99999).AsParallel().ForAll(n =>
{
var name
="Person"+ n %9;
list.Add(
new Person { Id = n, Name = name });
});
Console.WriteLine(
"Person's count is {0}", list.Count);
return list;
}

class Person
{
internalint Id { get; set; }
internalstring Name { get; set; }
}

  試驗結果如下(單位ms):

?次數

?1

?2

?3

?4

?Fill 方法

?37

?27

?26

?26

?FillParallel 方法

?43

?20

?19

?20

  這個結果有點奇妙的。第一次多線程居然還不如單線程快,和上文例子比較一下,有點明白了。稍微改了下代碼,在Add語句前加了個Thread.Sleep(1),并把 List<Person>集合元素減為999,試了一次,結果如下(單位ms):

?次數

?1

?2

?3

?4

?Fill 方法

?1012

?998

?998

?999

?FillParallel 方法

?547

?504

?504

?504

  多個線程協同工作時,分配任務本身有開銷,要是分配的開銷比任務本身還大,多線程就沒有意義了。就比如你交待別人做某件事,要是交待的功夫比自己做還長,還不如自己做。不過從結果也可以看出一個辯證關系,從長遠打算,第一次讓別人熟悉業務,付出點培訓成本,執行完一次后,以后就輕松多了,速度提高了一倍。如果這里Sleep一下,模擬長一點的單次處理過程,一開始多線程的優勢就會非常明顯。

  FillParallel方法,大家覺得有沒有其它問題呢?想必一般人都能看出,這里有最初級的線程安全問題。沒看出的應該是剛學.Net各種集合的初學者,線程安全對他們還只是個太虛幻境。不過借助這個Parallel,就可以輕松神游幻境。把FillParallel方法循環一百次執行,會發現返回結果本來應該有999個元素,輸出的卻顯示卻結果經常少十幾二十個。如果創建List時賦的容量不夠,在List擴容時,還可能引發異常。一般是像下圖這樣(不過一百次都是999也不是不可能,要看你的RP了):

  應提醒一點的是,試驗要在Release編譯模式下運行,不然看不到線程安全問題,并行執行的效率提升得也很有限。我用的電腦都是雙核,不知道在單核電腦的運行情況如何,可能有一定區別。

  接著我改下邏輯,增加了一個是否Person存在重名的判斷,變成:

代碼 static IEnumerable<Person> testFillParallel()
{
var list
=new List<Person>(9);

Enumerable.Range(
1, 999).AsParallel().ForAll(n =>
{
var name
="Person"+ n %9;
if (list.Count(p => p.Name == name) <1) list.Add(new Person { Id = n, Name = name });
});
Console.WriteLine(
"Person's count is {0}", list.Count);
return list;
}

  RP不管用了,執行幾次,必拋異常:System.InvalidOperationException: Collection was modified; enumeration operation may no execute.

  一個線程在枚舉集合元素,這時必須保證集合不被其它線程修改,怎么辦呢?以前,就知道用鎖,現在據說有了線程安全的集合類,在System.Collections.Concurrent命名空間下,有ConcurrentDictionary, ConcurrentQueue, ConcurrentStack,就是沒有ConcurrentList。費了半天,才發現與List對應的應該是BlockingCollection。

  把集合定義換成: var list = new BlockingCollection<Person>(9); 只見刷刷刷,哪怕執行幾萬次都可以一路跑完了。

  不過這樣做,還是會發現問題,不知大家看出了嗎?

總結

以上是生活随笔為你收集整理的.Net 4.0并行库实用性演练的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。