Destination Array not long enough?

后端 未结 4 1324
不知归路
不知归路 2020-12-08 13:07

I have a class with the following method:

public List bikesCopy 
{
     get 
     { 
       List bs;
       lock (_bikes) bs = new Li         


        
相关标签:
4条回答
  • 2020-12-08 13:34

    I would say the error lies in the object _bikes not being thread safe. As commented, somewhere there is a modify of the _bikes object that is not being lock'ed.

    It is a split second error where the variable bs is set up to a size X when the size of _bikes is measured. In the next split second as it is about to fill the list, the _bikes object has increased in size giving the error.

    So go over your code. Find all references of your _bikes object and make sure they are thread safe handled (with lock).

    0 讨论(0)
  • 2020-12-08 13:34

    This error occurs because multiple threads are adding items in a single list. Lists are by default not a thread-safe solution. In a multi-threaded code, it is only recommended to read from a list, and not write to it.

    As described here:

    If you are only reading from a shared collection, then you can use the classes in the System.Collections.Generic namespace.

    Better use a thread-safe solution like System.Collections.Concurrent namespace which provides implementations like ConcurrentBag, ConcurrentDictionary, ConcurrentQueue, ConcurrentStack etc.

    For example:

    public ConcurrentBag<Bike> bikesCopy 
    {
         get => new ConcurrentBag<Bike>()
    }
    
    0 讨论(0)
  • 2020-12-08 13:48

    Not really an answer, more a research comment.

    I ran into the same problem and did a quick test. I tried with the code below and could not get this code to throw the ArgumentException: Destination array was not long enough. But when I remove the .ToList() from the line

    return allLines.ToList().ToArray();
    

    it immediately crashes.

    This is the demo code and even the IDE tells me, I should remove the ToList() call as it seems redundant.

    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);
            }
        }
    }
    

    I really wonder, why it would not crash, as the List is also backed by an array.

    0 讨论(0)
  • 2020-12-08 13:49

    Well you could try:

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

    The details of the exception are discussed here: Why doesn't a foreach loop work in certain cases?

    0 讨论(0)
提交回复
热议问题