異常:System.ArgumentException: 目標數組的長度不夠。請檢查 destIndex 和長度以及數組的下限。(很差意思忘記截圖了)數組
發生異常的代碼以下:安全
var list = new List<Topic>(); Parallel.For(2, totalPage + 1, page => { //AddRange 方法發生異常 list.AddRange(GetTopics(board.BoardID, page)); });
緣由:List<T> 集合不是線程安全的,在併發操做 List 時,內部計算可能會出現問題。(具體內部會出現什麼問題,我這個菜鳥在這裏就不賣弄了,你們能夠反編譯看看 List 內部實現原理)併發
通過在StackOverflow上查找得知2種解決方法:如下爲原回答截圖性能
即:第一種,使用 lock 加鎖線程
private static readonly object locker = new object(); Parallel.For(2, totalPage + 1, page => { var range = GetTopics(board.BoardID, page); lock(locker) { list.AddRange(range); } });
第二種,使用 AsParallel().SelectMany 併發生成一個 Enumerablecode
//生成一個整數序列 var nums = Enumerable.Range(2, totalPage - 1); //使用 AsParallel 執行併發操做,並使用 SelectMany 將每一個元素映射爲新的對象,而後將結果合併爲一個集合 var range = nums.AsParallel().SelectMany(page => GetTopics(board.BoardID, page)); //同步增長到 List 中 list.AddRange(range);
通過在MSDN上查找,發現有一個命名空間下實現了一些線程安全集合類,以下圖對象
地址:https://msdn.microsoft.com/zh-cn/library/system.collections.concurrent(v=vs.100).aspxblog
上面這些線程安全集合類我暫時沒有用過,不過既然是微軟提供的,想必性能各方面都應該不錯,你們可根據適用場景自行選擇。get