2016-11-10 7 views
-3

を増加させないカウント私は、なぜこのコード理解スレッドはなぜ

static void Main(string[] args) 
    { 
     Console.WriteLine("START PROGRAMN-----------------------------------"); 
     test(); 
     Console.WriteLine("END PROGRAMN-----------------------------------"); 
     Console.Read(); 
    } 
    [ThreadStatic] 
    private static int i; 
    private static void test() 
    { 
     for (i = 0; i < 2; i++) 
     { 
      var bw = new BackgroundWorker(); 

      // define the event handlers 
      bw.DoWork += (sender, args) => 
      { 
       Console.WriteLine("START Thread-------------"); 
       Console.WriteLine("Print:" + i); 
      }; 
      bw.RunWorkerCompleted += (sender, args) => 
      { 
       Console.WriteLine("END Thread-------------"); 
       if (args.Error != null) 
       { 
        Console.WriteLine(args.Error.ToString()); 
       } 
      }; 

      bw.RunWorkerAsync(); // starts the 
     } 
    } 

とunrdersntatしていないそれは、コンソールでこれを表示します:

START PROGRAMN----------------------------------- 
END PROGRAMN----------------------------------- 
START Thread------------- 
Print:0 
END Thread------------- 
START Thread------------- 
Print:0 
END Thread------------- 

第二の印刷は、印刷1が表示されないのはなぜ?

私はprint:0を参照しているため、最初の反復は正しいと思いますが、2番目の理由は印刷されません:1? [ThreadStatic]

static void Main(string[] args) 
    { 
     Console.WriteLine("START PROGRAMN-----------------------------------"); 
     test(); 
     Console.WriteLine("END PROGRAMN-----------------------------------"); 
     Console.Read(); 
    } 
    [ThreadStatic] 
    private static int i; 
    private static void test() 
    { 
     for (i = 0; i < 2; i++) 
     { 
      var bw = new BackgroundWorker(); 

      // define the event handlers 
      bw.DoWork += (sender, args) => 
      { 
       Console.WriteLine("START Thread-------------"); 
       Console.WriteLine("Print:" + i); 
      }; 
      bw.RunWorkerCompleted += (sender, args) => 
      { 
       Console.WriteLine("END Thread-------------"); 
       if (args.Error != null) 
       { 
        Console.WriteLine(args.Error.ToString()); 
       } 
      }; 

      bw.RunWorkerAsync(); // starts the 
     } 
    } 

なしANSER

FOR

EDITそれはコンソールでこれを表示します:

START PROGRAMN----------------------------------- 
END PROGRAMN----------------------------------- 
START Thread------------- 
Print:2 
END Thread------------- 
START Thread------------- 
Print:2 
END Thread------------- 

最初pirnt印刷0と第二のプリント1が表示されないのはなぜ?

なぜ2を表示しますか?

+0

なぜこれをASP.NETにタグ付けしましたか? – mason

答えて

1

これを忘れてThreadStaticあなたはこれを正しく使用していません。あなたが必要とするものではありません。 DoEventが既に変更された最初のスレッドで開始されていないため、結果が最新の値になるため、バイパスしようとしている問題があります。あなたは競争状態に終わる。変数のローカルインスタンスをクリアするには、引数を使用する必要があります。最も簡単な方法は、あなたのチェックそう

for (int i = 0; i < 2; i++) 
{ 
    var bw = new BackgroundWorker(); 

    // define the event handlers 
    bw.DoWork += (sender, args) => 
    { 
      // get the argument 
      var value = args.Argument.ToString(); 
      Console.WriteLine("START Thread-------------"); 
      Console.WriteLine("Print:" + value); 
    }; 
    bw.RunWorkerCompleted += (sender, args) => 
    { 
     Console.WriteLine("END Thread-------------"); 
     if (args.Error != null) 
     { 
      Console.WriteLine(args.Error.ToString()); 
     } 
    }; 

    bw.RunWorkerAsync(i); // starts the thread with arguments 
} 
2

ここでは、ThreadStaticの属性を実際に理解していないと思います。これは、定義によって、Indicates that the value of a static field is unique for every thread.を意味します。これは、値がiのデフォルト値0を常に持つMainWork(BackgroundWorkersを作成している)とBackgroundWorkersで一意であることを意味します。

0

のようにコードを変更することです 'Console.WriteLineを( "印刷:" + i)を;'ラムダの内側にある。 "Print:" + iは評価されず、forループ内で連結されません。それはあなたの匿名メソッドに存在し、そのメソッドが実行されるときにのみ連結されます。

[ThreadStatic]属性のため、intはスレッド間で共有されません。 "実行中の各スレッドは、フィールドのインスタンスを個別に持ち、そのフィールドの値を独立して設定および取得します。異なるスレッドでフィールドにアクセスすると、異なる値が格納されます。

int私はインスタンス化され、intのデフォルト値を取得します。

関連する問題