1

これはこのフォーラムでの最初の質問なので、明確にしたいと思います:

C# で Visual Studio 2010 RTM プログラミングを使用しています。

スレッドに変換されるクラスのコンストラクターは、常に最後のディクショナリ エントリから値を取得します。私は何が間違っているのかわからない、誰か?

このコードは機能しません:

    Dictionary<string, Queue<string>> colas;

    public DataDispatcher(Dictionary<string, int> lectoras, ReadEventHandler callback)
    {
        colas = new Dictionary<string, Queue<string>>();

        foreach (KeyValuePair<string, int> pair in lectoras)
        {
            colas.Add(pair.Key, new Queue<string>>());

            Thread hilo = new Thread(
                () => new ReadHandler(pair.Value, colas[pair.Key], callback));

            hilo.Name = "Hilo-" + hilo.ManagedThreadId.ToString();

            hilo.Start();
        }
    }

代わりに、このコードは完全に機能します。

    Dictionary<string, Queue<string>> colas;

    public DataDispatcher(Dictionary<string, int> lectoras, ReadEventHandler callback)
    {
        colas = new Dictionary<string, Queue<string>>();

        foreach (KeyValuePair<string, int> pair in lectoras)
        {
            Queue<string> qs = new Queue<string>();

            colas.Add(pair.Key, qs);

            int jaula = pair.Value;

            Thread hilo = new Thread(
                () => new ReadHandler(jaula, qs, callback));

            hilo.Name = "Hilo-" + hilo.ManagedThreadId.ToString();

            hilo.Start();
        }
    }
4

2 に答える 2

2

これは、「ループ変数のキャプチャ」または「変数のクローズ」と呼ばれる非常に一般的なエラーです。

 foreach (KeyValuePair<string, int> pair in lectoras)
 {
     colas.Add(pair.Key, new Queue<string>>());  // here 'pair' is OK

     var copy = pair;  // this is the fix, make a new 'copy' for each thread

     Thread hilo = new Thread(
         () => new ReadHandler(copy.Value, colas[copy.Key], callback)); 
 }

すべて同じ変数を使用して、多数のスレッドを開始していましたpair。この「キャプチャされた」変数は、参照渡しパラメータのように動作します。スレッドが実行を開始するまでに、スレッドforeach()はすべて最後の要素を使用します。

ちなみに、これにはベアスレッドを使用しないでください。TPLのThreadPoolまたはTaskオブジェクトを使用します。

于 2012-06-29T19:40:41.147 に答える
1

はい。あなたは「キャプチャされた変数」と呼ばれるものの犠牲者です。ここでキャプチャされているのはpairです。この記事を参照してください: http://blog.sluu.org/captured-variable/

編集: OPの最初のスニペットに構文エラーがあることにも気付きました:colas = new Dictionary<string, Queue<string>>();この行には余分な大きな記号があります。

于 2012-06-29T19:44:06.987 に答える