10

ロギング コンテキスト情報を TLS に保存して、エントリ ポイントで値を設定し、その値を結果のすべてのスタックで使用できるようにしたいと考えています。これはうまくいきますが、TPL と ThreadPool も使用しています。問題は、TLS データを他のスレッドに移行する方法です。私はすべて自分で行うことができますが、Parallel.For のような便利なメソッドが失われます。

TPL を使用するときに TLS をコピーする方法はありますか? これは、await 機能を取得するときに C# にも適用されます。

ありがとう、エリック

4

3 に答える 3

5

通常、これは、既にスレッド ローカル データを提供しているParallel.Forのオーバーロードを使用して処理されます。

このオーバーロードにより、初期化とファイナライズのデリゲートを提供できます。これは、スレッド ローカル データのスレッドごとの初期化と、最後に結果を "マージ" するリダクション関数になります (スレッドごとに 1 回実行されます)。 これについては、こちらに詳しく書きました

基本的なフォームは、次のようなことです。

object sync = new object();
double result = 0;

Parallel.For(0, collection.Count, 
    // Initialize thread local data:
    () => new MyThreadSpecificData(),
    // Process each item
    (i, pls, currentThreadLocalData) => 
    {
        // Generate a NEW version of your local state data
        MyThreadSpecificData newResults = ProcessItem(collection, i, currentThreadLocalData);
        return newResults;
    },
    // Aggregate results
    threadLocalData =>
    {
       // This requires synchronization, as it happens once per thread, 
       // but potentially simultaneously
       lock(sync)
          result += threadLocalData.Results;
    });
于 2011-11-01T00:28:12.943 に答える
4

コードを必要としない問題の別の解決策を見つけました。CallContext を使用して、データを「論理スレッド」にアタッチすることができました。このデータは、開始スレッドから、TPL および ThreadPool によって生成されたスレッドに転送されます。

http://www.wintellect.com/CS/blogs/jeffreyr/archive/2010/09/27/logical-call-context-flowing-data-across-threads-appdomains-and-processes.aspx

于 2011-11-03T21:37:49.083 に答える
0

もちろん、さらに別の代替手段があります。現在の Thread ではなく、現在の Task に基づいてストレージを作成する TaskLocal(T) クラスを記述します。正直なところ、Microsoft が最初の Task 実装の一部としてこれを行わなかった理由がわかりません。

実装に関する重要な注意: await を呼び出す Task コードは分割され、別のTaskId として再開される可能性があるため、同様に行ったことを実行し、新しい TaskId を以前のものにマップする TaskLocal(T) にメソッドを実装してから保存する必要があります。タスクの開始時に元の TaskId を取得し、すべての await 呼び出しの後にマップします。

于 2015-07-21T17:34:08.720 に答える