1

以下の私のコードでは、のIdプロパティはThreadClass期待どおりに決定論的に設定されていません(ThreadArray[0]'s ThreadClass.Id = 0, ThreadArray[1]'s ThreadClass.Id = 1,など)。

デバッグして速度を落とすとThread.Start()'s、すべてが期待どおりに機能します。しかし、プログラムがフルスピードで実行されると、私はすべてId's = 4(または同様のもの)を取得します。i参照変数ではないため、ロックできません。明らかに、私は競合状態に遭遇しています。私は何が間違っているのですか?

Main.cs

for (int i = 0; i < ThreadCount; i++)
{
    ThreadArray[i] = new Thread(() =>
        {
            new ThreadClass(i);
        });
    ThreadArray[i].Start();
}

ThreadClass.cs

private int Id { get; set; }

public ThreadClass(int i) {
    Id = id;
    while(true)
    {
        Console.WriteLine("I am thread " + i");
        Thread.Sleep(5000);
    }
}

期待される出力:

I am thread 0
I am thread 1
I am thread 2
I am thread 3
... 5 second wait ...
I am thread 0
I am thread 1
I am thread 2
I am thread 3

実際の出力:

I am thread 4
I am thread 4
I am thread 4
I am thread 4
... 5 second wait ...
I am thread 4
I am thread 4
I am thread 4
I am thread 4

この時点で、の各インスタンスはThreadArray有効なThreadオブジェクトに初期化されることに注意してください。

4

2 に答える 2

2

i変数の新しいコピーを閉じないバージョンのC#を使用しています。スレッドが実行されるまでに、iは、またはその近くにありThreadCountます。変数のコピーを作成するだけで、クロージャーは代わりにそれをキャプチャできます。

for (int i = 0; i < ThreadCount; i++) 
{  
    int temp = i;
    ThreadArray[i] = new Thread(() =>  
        {              
            new ThreadClass(temp); 
        });      
}  

ちなみに、VS 2012(または.NET 4.5)のC#のバージョンでは、これが修正されています。http://msdn.microsoft.com/en-us/library/hh678682(v=vs.110).aspxを参照してください

于 2012-08-13T20:31:45.897 に答える
-1

ThreadArray [i] .Start()をforループの外に移動し、スレッドを開始する前にすべてのクラスを設定するだけです。2回ループする必要がありますが、すべてが希望する順序/状態で発生するようにする必要があります。

--EDIT Darnitは、私がやる直前に答えを得ました-:)

于 2012-08-13T20:29:17.507 に答える