0

このコードを実行したとき

      private void button1_Click(object sender, EventArgs e)
    {
        Start(sender, e);
    }

    private void Start(object sender, EventArgs e)
    {
        for (int i = 0; i < 5; i++)
        {
            System.Threading.Tasks.Task.Factory.StartNew(() => dosomething(i));
            Debug.WriteLine("Called " + i);
        }
        Debug.WriteLine("Finished");

    }
    public void dosomething(int i)
    {
        Debug.WriteLine("Enters " + i);
        lock (this)
        {
            Debug.WriteLine("Working " + i);
            Thread.Sleep(100);
        }
        Debug.WriteLine("Done " + i);
    }

.Net バージョン 4.0 と 4.5 では出力が異なります。4.0 では番号 5 が繰り返され、一部のタスクが実行される前に i の値が 5 に移動される理由がわかりますが、4.5 の同じコードは異なる出力を示します。

(出力はVS 2010 .Net 4.0で実行されました)

Called 0
Called 1
Enters 1
Working 1
Called 2
Called 3
Called 4
Finished
Enters 0
Done 1
Enters 5
Working 0
Working 5
Done 0
**Enters 5
Working 5
Done 5
Enters 5
Done 5
Working 5
Done 5**

しかし、.Net 4.5 (VS 2011 ベータ版) で実行したときの結果は、

(出力は VS 2011 beta .Net 4.5 で実行されました)

Enters 0
Working 0
Called 0
Called 1
Enters 2
Called 2
Enters 2
Enters 3
Called 3
Called 4
Finished
Done 0
Working 2
Enters 5
Done 2
Working 3
Done 3
Working 5
Done 5
Working 2
Done 2

CLR 4.5 のタスクで行われた変更を確認できませんでしたか? 誰でも.Net 4.5の変更点を教えてください。

4

2 に答える 2

1

コードに競合状態があります。タスクが開始される前にループの実行が終了したとします。これは完全に可能です。

次に、すべてのタスクで値が5になります。これはバグです。

解決策:iをループローカル変数にコピーし、このローカルをタスクのラムダで使用します。

于 2012-04-25T18:00:42.800 に答える
0

コードに競合状態があります。つまり、操作の正確な順序に応じて、さまざまな方法で動作できるということです。

また、小さな変更は操作の順序に影響を与える可能性があるため、フレームワークのバージョンが異なるとコードの動作が異なることは予想外ではありません。実際、同じバージョンの.netで複数回実行すると、動作が異なると思います。

于 2012-04-25T17:09:12.613 に答える