web-dev-qa-db-fra.com

Destination Array pas assez longtemps?

J'ai un cours avec la méthode suivante:

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

Ce qui fait une copie d'une autre liste, private List<Bike> _bikes;

La chose étrange est maintenant, que je reçois l'erreur suivante: 

Le tableau de destination n'était pas assez long. Vérifiez destIndex et la longueur, ainsi que les limites inférieures du tableau.

Quel est le problème ici?

39
Geert

Je dirais que l'erreur réside dans l'objet _bikes ne pas être thread-safe. Comme indiqué, quelque part il y a une modification de l'objet _bikes qui n'est pas bloquée.

C'est une erreur en une fraction de seconde où la variable bs est définie à une taille X lorsque la taille de _bikes est mesurée. Dans la fraction de seconde qui s’apprête à remplir la liste, la taille de l’objet _bikes a augmenté, ce qui donne l’erreur.

Alors examinez votre code. Recherchez toutes les références de votre objet _bikes et assurez-vous qu’elles sont traitées en toute sécurité (avec verrou).

74
Wolf5

Eh bien, vous pouvez essayer: 

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

Les détails de l'exception sont discutés ici: Pourquoi une boucle foreach ne fonctionne pas dans certains cas?

7
edvaldig

Pas vraiment une réponse, plus un commentaire de recherche.

J'ai rencontré le même problème et fait un test rapide ... J'ai essayé avec le code ci-dessous et je ne pouvais pas obtenir ce code pour lancer le ArgumentException: Destination array was not long enough. Mais quand je supprime la .ToList() de la ligne

return allLines.ToList().ToArray();

il se bloque immédiatement.

Ceci est le code de démonstration et même le IDE me dit que je devrais supprimer l'appel ToList() car il semble redondant.

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

Je me demande vraiment pourquoi il ne tomberait pas en panne, car la liste est également soutenue par un tableau.

0
Xan-Kun Clark-Davis