c# - TPL 数据流本地存储或类似的东西

标签 c# task-parallel-library tpl-dataflow

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

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

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

此 block 在服务中并连续运行数月。在那段时间里, block 的每个并发槽都使用了大量线程,因此线程本地存储是不合适的。我需要一些绑定(bind)到逻辑 block 插槽的东西。此 block 也永远不会完成,它运行服务的整个生命周期。

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

最佳答案

听起来您已经知道,Dataflow block 绝对不能保证 block 、执行和线程之间的相关性。即使将最大并行度设置为 4,所有 4 个任务也可以在同一个线程上执行。或者单个任务可能在多个线程上执行。

鉴于您最终想要为您的 n 并行度重用昂贵服务的 n 个实例,让我们暂时不考虑数据流,因为它不会帮助(或直接阻碍)您对此问题的任何通用解决方案。其实很简单。您可以使用 ConcurrentStack<T> , 其中T是实例化成本高昂的服务类型。您的代码出现在方法(或委托(delegate))的顶部,代表您的并行工作单元之一:

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() 作为数据流 block 的委托(delegate),就可以开始了。

当然,ConcurrentStack<T> 并没有什么神奇之处在这里,除了 push 和 pop 周围的锁是内置在类型中的,所以你不必自己做。

关于c# - TPL 数据流本地存储或类似的东西,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15265761/

相关文章:

c# - 在 .NET 核心中使用 app.config 和 ConfigurationManager 是否可取?

c# - 是否有一种有效的方法来处理 Visual Studio 中重复的 XML 注释 C# 代码

c# - Task.WhenAll 结果排序

c# - TPL 完成与完成

c# - 具有永久任务/线程的 TPL 数据流 block

c# - 如何从多个源异步加载 ASP.NET GridView?

c# - 如何在不安装整个 SDK 的情况下在 Docker 中运行 .net 单元测试?

c# - WPF 异步等待任务锁定 UI 线程并行运行任务

c# - 在任务上排队的延续是否总是在完成任务的线程上执行?

c# - TPL数据流优化