1

私が達成しようとしているのは、でアクションブロックを持っていることですMaxDegreeOfParallelism = 4。並列パスごとにセッション オブジェクトのローカル インスタンスを 1 つ作成したいので、合計 4 つのセッション オブジェクトが必要です。これがスレッドの場合、次のようなものを作成します。

 ThreadLocal<Session> sessionPerThread = new ThreadLocal<Session>(() => new Session());

ブロックはスレッドではないことを知っているので、同様のものを探していますが、ブロック用です。これを作成する方法はありますか?

このブロックはサービス中であり、何ヶ月も継続して実行されます。その間、ブロックの同時スロットごとに大量のスレッドが使用されるため、スレッド ローカル ストレージは適切ではありません。論理ブロック スロットに関連付けられたものが必要です。また、このブロックは決して完了せず、サービスの存続期間全体を実行します。

注:上記の提案された回答は、私が求めているものには無効です。私は具体的にスレッドローカルとは異なるものを求めており、上記の答えはスレッドローカルを使用しています。これはまったく別の質問です。

4

1 に答える 1

4

ご存知のように、Dataflow ブロックは、ブロック、実行、およびスレッド間の相関関係をまったく保証しません。最大並列処理が 4 に設定されていても、4 つのタスクすべてが同じスレッドで実行される可能性があります。または、個々のタスクが多くのスレッドで実行される場合もあります。

n度の並列処理に対して高価なサービスのnインスタンスを最終的に再利用したい場合、データフローを完全に無視してみましょう。問題。それは実際には非常に簡単です。を使用できます。ここで、はインスタンス化にコストがかかるサービスのタイプです。メソッド (またはデリゲート) の先頭に、並列作業単位の 1 つを表すコードがあります。ConcurrentStack<T>T

private ConcurrentStack<T> reusableServices;

private void DoWork() {
    T service;
    if (!this.reusableServices.TryPop(out service)) {
        service = new T(); // expensive construction
    }

    // Use your shared service.
    //// Code here.

    // Put the service back when we're done with it so someone else can use it.
    this.reusableServices.Push(service);
}

このようにして、 の並列実行とまったく同じ数の高価なサービスのインスタンスを作成することがすぐにわかりますDoWork()。期待する並列度をハードコーディングする必要さえありません。また、その並列処理を実際にスケジュールする方法とは直交しています (したがって、スレッドプール、データフロー、PLINQ などは問題ではありません)。

したがって、DoWork() を Dataflow ブロックのデリゲートとして使用するだけで準備完了です。

もちろん、ConcurrentStack<T>プッシュとポップの周りのロックが型に組み込まれているため、自分で行う必要がないことを除けば、魔法のようなことは何もありません。

于 2013-03-08T03:53:42.153 に答える