目标阵列不够长?

时间:2012-04-28 08:50:35

标签: c# list locking

我有一个使用以下方法的课程:

public List<Bike> bikesCopy 
{
     get 
     { 
       List<Bike> bs;
       lock (_bikes) bs = new List<Bike>(_bikes);
       return bs;
     }
}

其中包含另一个列表private List<Bike> _bikes;

的副本

现在奇怪的是,我收到以下错误:

  

目标数组不够长。检查destIndex和length,以及数组的下限。

这里有什么问题?

4 个答案:

答案 0 :(得分:76)

我会说错误在于 _bikes 对象不是线程安全的。如评论所述,在某处可以修改未被锁定的 _bikes 对象。

这是一个瞬间错误,当测量 _bikes 的大小时,变量 bs 设置为X大小。在即将填充列表的下一个瞬间, _bikes 对象的大小增加,从而产生错误。

请仔细阅读您的代码。查找 _bikes 对象的所有引用,并确保它们是线程安全处理(带锁定)。

答案 1 :(得分:7)

你可以试试:

using System.Linq; //ToList() is an extension function defined here
...
lock(_bikes)
    return _bikes.ToList();

此处讨论了例外的详细信息:Why doesn't a foreach loop work in certain cases?

答案 2 :(得分:1)

发生此错误是因为多个线程正在单个列表中添加项目。默认情况下,列表不是线程安全的解决方案。在多线程代码中,仅建议从列表中读取而不是写入列表。

here所述:

如果您仅从共享馆藏中阅读,则可以使用 System.Collections.Generic命名空间中的类。

最好使用诸如System.Collections.Concurrent命名空间之类的线程安全解决方案,该解决方案提供诸如ConcurrentBagConcurrentDictionaryConcurrentQueueConcurrentStack等实现。

例如:

public ConcurrentBag<Bike> bikesCopy 
{
     get => new ConcurrentBag<Bike>()
}

答案 3 :(得分:0)

不是真正的答案,更多是研究评论。

我遇到了同样的问题并进行了快速测试。 我尝试使用下面的代码,无法使用此代码抛出ArgumentException: Destination array was not long enough。但是当我从行

中删除.ToList()
return allLines.ToList().ToArray();
它会立即崩溃。

这是演示代码,即使IDE告诉我,我应该删除ToList()调用,因为它似乎是多余的。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace ConsoleApp1
{
    class Program
    {
        static void Main() {

            List<string> thelist = new List<string>();

            Thread producer = new Thread(() => {
                while (true) {
                    thelist.Add("a" + DateTime.Now);
                }
            });

            Thread transformer = new Thread(() => {
                while (true) {
                    string[] thearray = thelist.ToList().ToArray();
                    Console.WriteLine(thearray.Length);
                }
            });
            producer.Start();
            transformer.Start();
            Console.ReadKey(true);
        }
    }
}

我真的很想知道,为什么它不会崩溃,因为List也有一个数组支持。