2017-10-15 2 views
2

は、TPLのタスク構成とthreadlocalの悪用のケースについて話している、本の本の例を理解することはできません。TPLのTaskでC#ThreadLocalが期待通りに動作しないのはなぜですか?

期待される結果が10000になっていないのはなぜですか?

誰でもすぐに実行する行と非同期で実行する行のプログラムフローの詳細について説明してください。シーケンスと実行順序?

using System; 
using System.Threading; 
using System.Threading.Tasks; 

namespace Listing_05 { 

class BankAccount { 
    public int Balance { 
     get; 
     set; 
    } 
} 

class Listing_05 { 

    static void Main(string[] args) { 

     // create the bank account instance 
     BankAccount account = new BankAccount(); 

     // create an array of tasks 
     Task<int>[] tasks = new Task<int>[10]; 

     // create the thread local storage 
     ThreadLocal<int> tls = new ThreadLocal<int>(() => { 
      Console.WriteLine("Value factory called for value: {0}", 
       account.Balance); 
      return account.Balance; 
     }); 

     for (int i = 0; i < 10; i++) { 
      // create a new task 
      tasks[i] = new Task<int>(() => { 

       // enter a loop for 1000 balance updates 
       for (int j = 0; j < 1000; j++) { 
        // update the TLS balance 
        tls.Value++; 
       } 

       // return the updated balance 
       return tls.Value; 

      }); 

      // start the new task 
      tasks[i].Start(); 
     } 

     // get the result from each task and add it to 
     // the balance 
     for (int i = 0; i < 10; i++) { 
      //added by myself to see any hints but still cannot have insights 
      Console.WriteLine("task {0} results {1}", i, tasks[i].Result); 
      //end of my editing 

      account.Balance += tasks[i].Result; 
     } 

     // write out the counter value 
     Console.WriteLine("Expected value {0}, Balance: {1}", 
      10000, account.Balance); 

     // wait for input before exiting 
     Console.WriteLine("Press enter to finish"); 
     Console.ReadLine(); 
    } 
} 

} 8つのコアI7のCPUを使用して、コンピュータに

結果、8つのスレッドでなければなりません。いくつかの回以下の実行は、多くの実行のうち2回です。

1st execute

2nd execute

+0

https://particular.net/blog/the-dangers-of-threadlocalを参照してください –

+0

はい、私は上記の質問に先立って上記のリンクをGoogleで行ったことがありますが、おそらく私はこのスレッドのトピックの初心者ですプログラムがこのようにふるまう理由。これまでのところ、ThreadLocalはスレッド専用のデータです。タスクは、未知のワーカースレッドによって実行されるタスクを記述する宣言型です。スレッドローカル初期化されたデータが10のタスクのうちいくつかのためにクラッシュするのは不明です同じタスクが10のタスクの一部で既に変更されていますか?誰かがこのサンプルの実行方法を記述できますか?実行するためにいくつかの行を延期する必要がありますか? – Cuda

+0

@Cuda、バリューファクトリーには2つの 'account.Balance'があります。両方とも異なる結果を返すことができます。 – PetSerAl

答えて

2

タスクが同時にコードを実行するためのメカニズムを提供し、この方法でプログラムがどのように動作するかを理解し、行動しません。これは必ずしも別々のスレッドで実行されることを意味するものではなく、複数のスレッドが再利用されない場合でも使用されます。

タスクでスレッドローカルストレージを使用しないでください。

代替ストレージオプションは、タスクのラムダ関数内でクロージャを使用するか、クラスを作成してそのクラスにデータを配置し、そのクラスのメソッドをタスクの呼び出し先として使用することです。私は個人的にはこれがとにかくきれいだと感じています。

ハンス・パッセントもAsyncLocalとコメントしています(これは私自身は使用していないのでコメントできません)。

+0

つまり、タスクを同時に実行する1つのスレッドまたはタスクを並行して実行する複数のスレッドがある可能性があります。つまり、スレッドの再利用を保証するものではありません。データストレージのタスクには何を使用する必要がありますか? – Cuda

関連する問題