我想设置TransformBlock
并行处理其项目。因此,我将ExecutionDataflowBlockOptions.MaxDegreeOfParallelism
设置为> 1.我不关心消息的顺序,但documentation说:
如果指定的最大并行度大于1,则会同时处理多个消息,因此,可能无法按接收顺序处理消息。但是,从块输出消息的顺序将正确排序。
“正确排序”是否表示如果队列中有一条消息需要较长的处理时间,则在处理完这一条消息之前不会输出更多消息?
如果是这样,我如何指定不关心排序的执行块(例如TransformBlock
)?或者我必须在消费端指定我不关心订购?
答案 0 :(得分:5)
库中没有这样的块,但您可以通过组合ActionBlock
和BufferBlock
轻松创建一个。类似的东西:
public static IPropagatorBlock<TInput, TOutput>
CreateUnorderedTransformBlock<TInput, TOutput>(
Func<TInput, TOutput> func, ExecutionDataflowBlockOptions options)
{
var buffer = new BufferBlock<TOutput>(options);
var action = new ActionBlock<TInput>(
async input =>
{
var output = func(input);
await buffer.SendAsync(output);
}, options);
action.Completion.ContinueWith(
t =>
{
IDataflowBlock castedBuffer = buffer;
if (t.IsFaulted)
{
castedBuffer.Fault(t.Exception);
}
else if (t.IsCanceled)
{
// do nothing: both blocks share options,
// which means they also share CancellationToken
}
else
{
castedBuffer.Complete();
}
});
return DataflowBlock.Encapsulate(action, buffer);
}
这样,一旦ActionBlock
处理了某个项目,它就会立即转移到BufferBlock
,这意味着不会维护订单。
这段代码的一个问题是它没有很好地观察集合BoundedCapacity
:实际上,这个块的容量是选项中设置容量的两倍(因为这两个块中的每一个都有一个分开的能力)。
答案 1 :(得分:0)
DataflowBlockOptions
类包含一个可配置属性EnsureOrdered
(于2016年引入),该属性确定是否将接收到的消息的顺序保留在块的输出中。默认情况下,此属性为true
。将此属性设置为false
可使该块在消息被处理后立即传播,由于传播速度更快且开销减少,因此增加了管道的吞吐量。