码迷,mamicode.com
首页 > 编程语言 > 详细

小记:目标数组的长度不够。请检查 destIndex 和长度以及数组的下限。

时间:2015-07-12 20:16:15      阅读:251      评论:0      收藏:0      [点我收藏+]

标签:

异常: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

技术分享

上面这些线程安全集合类我暂时没有用过,不过既然是微软提供的,想必性能各方面都应该不错,大家可根据适用场景自行选择。

 

小记:目标数组的长度不够。请检查 destIndex 和长度以及数组的下限。

标签:

原文地址:http://www.cnblogs.com/wynn0123/p/4641342.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!