2011-08-01 16 views
14

ThreadStaticのようなものは、どのようにTPLタスクで使用できますか?私の理解(「C#でのWrox Professional並列プログラミング」、p74)は、タスクが実行中にあるスレッドから別のスレッドに切り替えることができるということです。ThreadStatic for TPLタスク

私は何をしたいですか?

静的クラス内にセッションIDを保持したいので、このIDをすべてのメソッドに渡す必要はありません。私の図書館には、login(id)logout(id)などのメソッドと、このIDに関連付けられた資格情報で動作するメソッドがあります。しかし、私はすべての方法にこのidを渡したくない。私は、私のライブラリが別のセッションで別のスレッド内で呼び出されるようにすることができます。したがって、login()のIDをThreadStatic変数に保存すると動作します。

今私はThreadPoolによって私のために作成されたTPLタスクを使用したいと思います。セッションIDをタスクに渡すことはできますが、このIDをThreadStatic変数に格納すると、タスクがスレッドを切り替えると生き残りません。

+2

私は実際*タスクの聞いたことがない*実行中に別のスレッドからの切り替え。あなたはそのことについてどこで聞いたのですか? –

+2

ワーカースレッド間のタスク切り替えを示すブック "Wrox Professional Parallel Programming with C#"の74ページにある図があります。 – Gerard

+1

@Gerard:あるスレッドで*キューに入っているタスクではなく、*を実行している間に*実行中であることを確認してから、別のスレッドに切り替えて実行することを意味しますか? –

答えて

1

あなたは正しいですが、thread-staticはタスクには適していません。

パラメータを渡すことで問題が改善された方がよいでしょう。それは単にそれを渡すためにははるかに明確で清潔です。少しタイピングすると、読みやすさとスレッドの安全性がさらに向上します。

+0

ありがとうございます。それは私が恐れていたものです。私は多くのレベルの関数の多くを呼び出す必要があります。実際にはすべての関数にはセッションIDパラメータが必要です。この問題を解決する他のアイデアですか? – Gerard

2

どのスレッドがどのスレッドで実行されているかについていくつかの保証がない限り、静的なスレッドは避けてください。ちょうどそれを渡す。あなたの意図はより明確になります。

4

あなたがThreadStaticを使用するのと同じ方法でCallContext.LogicalSetData(string, object)CallContext.GetLogicalData(string)を使用できることを意味しますTPLと.NET 4.5の非同期フローExecutionContext、。ただし、パフォーマンス上の大きなペナルティが発生します。

深いダイビングについては、Async Causality Chain Tracking,、およびExecutionContext vs SynchronizationContextを参照してください。

使用例:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Logger.Current = new Logger("Test Printer"); 

     Logger.Current.Print("hello from main"); 
     var t1 = Task.Run(() => { Logger.Current.Print("hello from thread " + Thread.CurrentThread.ManagedThreadId); }); 
     var t2 = Task.Run(() => { Logger.Current.Print("hello from thread " + Thread.CurrentThread.ManagedThreadId); }); 
     Task.WaitAll(t1, t2); 
    } 
} 

class Logger 
{ 
    private string LogName; 

    public Logger(string logName) 
    { 
     if (logName == null) 
      throw new InvalidOperationException(); 

     this.LogName = logName; 
    } 

    public void Print(string text) 
    { 
     Console.WriteLine(LogName + ": " + text); 
    } 

    public static Logger Current 
    { 
     get 
     { 
      return CallContext.LogicalGetData("PrinterName") as Logger; 
     } 
     set 
     { 
      CallContext.LogicalSetData("PrinterName", value); 
     } 
    } 
} 

プリント:

 
Test Printer: hello from main 
Test Printer: hello from thread 11 
Test Printer: hello from thread 10 
関連する問題