3
public void GatherDataFromSwitches(Device[] switches)
{
    List<Thread> workerThreads = new List<Thread>();
    for(int i = 0; i < switches.Length - 1; i++)
    {
        Thread t = new Thread(unused => GatherDataFromSwitch(switches[i]));
        workerThreads.Add(t);
        t.Start();
    }
    foreach (Thread d in workerThreads) d.Join(); //wait for all threads to finish
}

そのメソッドを実行した後にスイッチをループすると、一部のスイッチにはデータが追加されておらず、一部のスイッチには複数のスイッチからデータが追加されていることがわかります。そのため、参照をワーカー スレッドに渡す際に問題が発生しました。正確にはまだわかりませんが、追加することで問題を解決しました

Thread.Sleep(100); 

直後の

t.Start();

新しく作成されたスレッドは、次のスレッドが作成される前に初期化する時間があるため、これが機能すると想定しています。しかし、これは回避策であり、修正ではありません。ラムダ式がどのように機能するかが原因ですか?

これを適切に回避するにはどうすればよいですか?

4

2 に答える 2

3

問題はi、ラムダでキャプチャされる方法です。ループ内でローカル コピーを作成して、各ラムダが個別の値をキャプチャするようにします。

public void GatherDataFromSwitches(Device[] switches)
{      
    List<Thread> workerThreads = new List<Thread>();
    for(int i = 0; i < switches.Length ; i++)
    {
        int j = i; // local i
        Thread t = new Thread(unused => GatherDataFromSwitch(switches[j]));
        workerThreads.Add(t);
        t.Start();
    }
    foreach (Thread d in workerThreads) d.Join(); //wait for all threads to finish
}

iまたは、パラメーターとして明示的にスレッドに渡します。

public void GatherDataFromSwitches(Device[] switches)
{      
    List<Thread> workerThreads = new List<Thread>();
    for(int i = 0; i < switches.Length ; i++)
    {
        Thread t = new Thread(param => { j = (int)param; GatherDataFromSwitch(switches[j]); });
        workerThreads.Add(t);
        t.Start(i);
    }
    foreach (Thread d in workerThreads) d.Join(); //wait for all threads to finish
}
于 2012-06-07T09:39:59.847 に答える
0
public void GatherDataFromSwitches(Device[] switches) {
     List<Thread> workerThreads = new List<Thread>();
     for(int i = 0; i < switches.Length ; i++)
     {
         int j = i;
         Thread t = new Thread(unused => GatherDataFromSwitch(switches[j]));
         workerThreads.Add(t);
         t.Start();
     }
     foreach (Thread d in workerThreads) d.Join(); //wait for all threads to finish 
}

iへのコピーに注意してくださいj。resharper を使用している場合、コードで警告が生成されます。詳細については、変更されたクロージャへのアクセスに関する質問を参照してください。

于 2012-06-07T09:41:00.747 に答える