如果我有多个数据源(例如来自数据库),然后执行一些CPU绑定工作,我如何使用TPL DataFlow表示这个?
我注意到TransformBlock有一个输入源,但是输入来自多个源,我想做大部分的并行操作来实现这个目的。
使用常规TPL或并行扩展来执行数据库的IO绑定工作,然后将这些数据合并到TransformBlock的一个点是最好的方法吗?
答案 0 :(得分:2)
看看JoinBlock,它可能就是您所需要的。
您还可以创建一个Custom Dataflow Block Type,可以实现您想要达到的目标。
例如,如果您希望5个对象到达,那么在您处理"之前他们,并返回一个单独的对象(我在这里使用expando来展示...),到一个接收器(也应该异步等待):
public sealed class YourCustomBlock : IPropagatorBlock<ExpandoObject, ExpandoObject>
{
// The target part of the block. coming in
private readonly ITargetBlock<ExpandoObject> m_target;
// The source part of the block. going out
private readonly ISourceBlock<ExpandoObject> m_source;
// dependency count
private readonly int _size ;
// temporary holding area of incoming stuff
private Queue<ExpandoObject> _queue;
public YourCustomBlock(int inputs)
{
_size = inputs;
_queue = new Queue<ExpandoObject>(_size);
var mainWorker= new TransformBlock<ExpandoObject[], ExpandoObject> (async expandoArray =>
{
// Do Your Stuff with expandoArray and then return something
// ExpandoObject in this example
await Task.Delay(1000).ConfigureAwait(false);
return /*Some ExpandoObject */;
});
var head = new ActionBlock<ExpandoObject>(async item =>
{
_queue.Enqueue(item);
if (_queue.Count > _size)
{
_queue.Dequeue();
}
// Post when you reach
// the size
if (_queue.Count == _size)
{
await mainWorker.SendAsync(_queue.ToArray());
_queue.Clear();
}
});
// expose as a block
m_source = mainWorker;
m_target = head;
}
}
样品使用:
var myBlock = new YourCustomBlock(5);
Task.Run(async () => {
for (var i=0;i<5;i++) {
await myBlock.SendAsync(/*SomeExpandoObject*/).ConfigureAwait(false);
}
});
var results = await myBlock.ReceiveAsync().ConfigureAwait(false);
注意:这还没有经过编译检查,只是这个想法的一个例子。