9

スレッドで特定のパラメーターを使用してメソッドを実行する必要があります。実行すると、パラメーターが間違っていることに気付きました。int[] outputこの例では、1 ~ 7 の数字の配列があります。番号ごとに、メソッドでスレッドを作成しますWriteInt(i)。出力は任意の順序で 1 ~ 7 になると予想していますが、一部の数字が欠落しており、他の数字が重複していることが一貫して見られます。これらのスレッドを開始する正しい方法は何ですか?

(リストは後でスレッドに参加するためだけに存在します)

class Program
{
    static void Main(string[] args)
    {
        int[] output = { 1, 2, 3, 4, 5, 6, 7 };

        List<Thread> runningThreads = new List<Thread>();

        foreach (int i in output)
        {
            Thread thread = new Thread(() => WriteInt(i));
            thread.Start();
            runningThreads.Add(thread);
        }
        foreach(Thread t in runningThreads)
        {
            t.Join();
        }
    }

    private static void WriteInt(int i)
    {
        Console.WriteLine(i);
    }
}

出力例:

3
3
4
5
6
7
4

1 に答える 1

14

ラムダ ( ) によって作成されたクロージャーは、各反復内で設定された値ではなく、変数() => WriteInt(i)を閉じています。スレッドが実行されると、その時点で設定された値が使用されます。これは、ループ処理のために既に変更されている可能性があります。 iiiforeach

あなたは一時的に必要です:

foreach (int i in output)
{
        int temp = i;
        Thread thread = new Thread(() => WriteInt(temp));
        thread.Start();
        runningThreads.Add(thread);
}

何が起こっているかについての詳細は、Eric Lippert の「有害と見なされるループ変数を閉じる」というタイトルの投稿を参照してください。

foreachまた、C# 5 (VS2012) では、これはループの問題ではなくなりました。ただし、for ループでは引き続き発生します。

于 2012-09-07T19:26:59.893 に答える