C# TPL数据流数据回收

C# TPL数据流数据回收,c#,task-parallel-library,tpl-dataflow,recycle,C#,Task Parallel Library,Tpl Dataflow,Recycle,我正在开发一个音频处理工具,我想使用TPL数据流构建它。 数据流本身将包括在声音处理块之间传递的音频样本。这些示例的大小通常为几Kb(float[]/byte[],包含1k到4k个元素)。 因此,数据流是一个简单的管道,如下所示: SourceBlock<byte[]> -> TransformBlock<byte[], float[]> -> TransformBlock<float[], float[]>

我正在开发一个音频处理工具,我想使用TPL数据流构建它。 数据流本身将包括在声音处理块之间传递的音频样本。这些示例的大小通常为几Kb(
float[]
/
byte[]
,包含1k到4k个元素)。 因此,数据流是一个简单的管道,如下所示:

SourceBlock<byte[]> 
    -> TransformBlock<byte[], float[]> 
        -> TransformBlock<float[], float[]>
            -> ...
SourceBlock
->转换块
->转换块
-> ...
一些块可以完全“就地”工作,即通过改变输入数据,而另一些块必须创建新样本。每个块的处理时间可能因输入中的数据而异


我不想一直分配新的数组,而依赖垃圾收集器来处理对象回收。 我希望从块的并发执行中获益,因此不希望限制链按顺序处理数据(在这种情况下,我无论如何都不需要TPL)。 我不需要处理块来运行并发处理(在任何给定时间,每个块最多只能有一个进程)


控制给定时间管道中样本数量并回收不再使用的样本/阵列的最佳方案是什么?

如果您的目标是重用阵列,而不是总是创建新阵列并让GC收集它们,则需要使用:

对象池模式是一种软件创造性设计模式,它使用一组随时可用的初始化对象(即“池”),而不是按需分配和销毁它们。池的客户端将从池中请求一个对象,并对返回的对象执行操作。当客户端完成时,它将对象返回到池中,而不是销毁它;这可以手动或自动完成


不幸的是,您可能需要自己实现它并使其线程安全。

“我不想一直分配新的阵列并依靠垃圾收集器来处理对象回收。”为什么这是您的解决方案的要求?垃圾收集是否会影响您的性能?如果是,您的目标是什么?我希望此代码能够在使用xamarin的手机上运行,这样内存占用就很重要了。很难测试所有场景(尤其是硬件),因此必须先发制人地识别和解决可能出现的问题。我最初的想法是处理器生成两个数据,一个处理结果和一个要回收的“垃圾”。后者将通过管道传输到上游处理器(有效地在网格中创建一个循环)。不确定这是一个可行的选择。这听起来是一个很好的解决方案。我认为我应该尝试根据请求线程优化回收(就像concurrentBag所做的那样)。你觉得怎么样?@LauLu你正在进入微优化领域。。。您知道TPL数据流块是否为每个项目使用专用线程吗?我认为围绕ConcurrentQueue的阻塞集合很好。我尝试了ObjectPool,一旦我做对了,它就完成了,谢谢。就性能而言,几乎没有影响,但我现在使用的内存要少得多。哈!TPL数据流为我们免费提供了线程安全的对象池。
BufferBlock
非常适合这项工作。使用
blk.Post(new float[4096])
将一些缓冲区放入其中,然后您可以
blk.Receive()
,使用它并在使用完毕后将其发回。
BufferBlock
上的其他方法可能会导致一个更奇特的对象池,您可以在其中异步等待一个项目变为可用。很遗憾,您没有发现它在这方面的用处:(@spender您只需要一个
BufferBlock
来异步阻塞(在对象池中通常不这样做,而是创建新项).
ConcurrentQueue
/
Stack
非常适合这一点,这是我的建议。在任何情况下……使用
BufferBlock
或其他集合正是我构建对象池的意思(没有人希望您为此编写自己的基元集合)。您不能(或不应该)做什么我们要做的是,根据OP的要求,通过控制管道中的项目数量,将现有的TPL数据流管道重用为池。