程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 小記:目標數組的長度不夠。請檢查 destIndex 和長度以及數組的下限。,小記destindex

小記:目標數組的長度不夠。請檢查 destIndex 和長度以及數組的下限。,小記destindex

編輯:C#入門知識

小記:目標數組的長度不夠。請檢查 destIndex 和長度以及數組的下限。,小記destindex


異常: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種解決方法:以下為原回答截圖

地址:http://stackoverflow.com/questions/8796506/correct-way-to-guarantee-thread-safety-when-adding-to-a-list-using-parallel-libr

即:第一種,使用 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 並發生成一個 Enumerable

//生成一個整數序列
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).aspx

上面這些線程安全集合類我暫時沒有用過,不過既然是微軟提供的,想必性能各方面都應該不錯,大家可根據適用場景自行選擇。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved