1

我想要完成的是我有一个带有MaxDegreeOfParallelism = 4. 我想为每个并行路径创建一个会话对象的本地实例,所以我想要总共 4 个会话对象。如果这是线程,我会创建类似的东西:

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

我知道块不是线程,所以我正在寻找类似但块的东西。有什么方法可以创建这个吗?

该块处于服务状态并连续运行数月。在此期间,块的每个并发槽使用大量线程,因此线程本地存储不合适。我需要一些与逻辑块插槽相关的东西。此外,此块永远不会完成,它会运行服务的整个生命周期。

注意:上述建议的答案对我的要求无效。我特别要求与线程本地不同的东西,上面的答案是使用线程本地。这完全是一个不同的问题。

4

1 回答 1

4

As it sounds like you already know, Dataflow blocks provide absolutely no guarantee of correlation between blocks, execution, and threads. Even with max parallelism set to 4, all 4 tasks could be executing on the same thread. Or an individual task may execute on many threads.

Given that you ultimately want to reuse n instances of an expensive service for your n degrees of parallelism, let's take dataflow completely out of the picture for a minute, since it doesn't help (or directly hinder) you from any general solution to this problem. It's actually quite simple. You can use a ConcurrentStack<T>, where T is the type of your service that is expensive to instantiate. You have code that appears at the top of the method (or delegate) that represents one of your parallel units of work:

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);
}

Now in this way, you can quickly see that you create exactly as many instances of your expensive service as you have parallel executions of DoWork(). You don't even have to hard-code the degree of parallelism you expect. And it's orthogonal to how you actually schedule that parallelism (so threadpool, Dataflow, PLINQ, etc. doesn't matter).

So you can just use DoWork() as your Dataflow block's delegate and you're set to go.

Of course, there's nothing magical about ConcurrentStack<T> here, except that the locks around push and pop are built into the type so you don't have to do it yourself.

于 2013-03-08T03:53:42.153 回答