2012-04-25 31 views
0

私は、コードのこの部分を実行したとき.Net 4.0と.Net 4.5のタスクを使用していますか?

 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で異なる理由がわかります。

(出力は.NET 4.0 VS 2010で走っ)

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ベータ版で走りました。 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の変更点を教えてください。

答えて

0

コードにrace conditionがあります。つまり、操作の正確な順序に応じてさまざまな方法で動作できます。

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

+0

私は注文について気にしませんが、私は値が.Net 4.0ではスレッド間で共有されていますが、.Net 4.5では共有されないことを見ています。 – murali

+0

'Start()'の 'i'変数はどちらの場合でも共有されます。正確に何が起こるかは操作の順序に依存します。 – svick

+0

あなたのお時間をありがとう...だから、あなたのポイントは、4.5と変更されていない、結果は操作の順序が異なるためですか?私はそうは思わない、何故これを言っているのか?出力を伴うアクションの順序を観察すると、一時停止後にのみ値が影響を受けます。私は何度も何度もテストしましたが、順序は異なりますが、結果は上記と同じです... – murali

1

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

次に、私はすべてに5の値を持っています。これはバグです。

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

+0

返信ありがとう、私はSystem.Threading.Tasks.Task.Factory.StartNew(オブジェクトo)=> dosomething(i)、i);私の質問はどのように動作させるのではなく、どのような変更がCLR 4.5で行われたのでしょうか? – murali

+0

@ムラリその質問は無意味です。順序は単純に定義されておらず、ランタイムの同じバージョンで異なるラン間で一貫している必要はありません。 – CodesInChaos

+0

新しいCLRはタスクを開始するときに効率が良いと思います。そのため、(非決定的な)秩序が変わった。 Btw、これは未定義の動作ではありません。これは明確に定義されていますが、非決定論的です。 – usr

関連する問題