web-dev-qa-db-ja.com

宛先配列の長さが足りませんか?

私は次のメソッドを持つクラスを持っています:

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

別のリストのコピーを作成します、private List<Bike> _bikes;

奇妙なことは、次のエラーが表示されることです。

宛先配列の長さが足りませんでした。 destIndexと長さ、および配列の下限を確認してください。

ここで問題は何ですか?

44
Geert

エラーはオブジェクトにあると言えます_ bikesスレッドセーフではありません。コメントしたように、ロックされていない_ bikesオブジェクトの変更がどこかにあります。

これは、_ bikesのサイズが測定されたときに変数bsがサイズXに設定されているという、一瞬のエラーです。リストを埋めようとしている次の一瞬で、_ bikesオブジェクトのサイズが大きくなり、エラーが発生します。

だからあなたのコードを調べてください。 _ bikesオブジェクトのすべての参照を見つけ、それらがスレッドセーフで処理されることを確認します(ロックあり)。

81
Wolf5

さてあなたは試すことができます:

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

例外の詳細は次のとおりです。 特定の場合にforeachループが機能しないのはなぜですか?

7
edvaldig

本当の答えではなく、研究のコメントです。

同じ問題にぶつかり、簡単なテストを行いました。以下のコードを試しましたが、このコードを取得して_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);
        }
    }
}
_

リストも配列によって支えられているので、なぜクラッシュしないのか、本当に疑問に思います。

0