TPL Dataflow LinkTo TransformBlock非常慢

时间:2018-03-20 23:21:15

标签: c# .net task-parallel-library dataflow tpl-dataflow

我有两个循环排列的TransformBlocks。他们将数据相互链接。 TransformBlock 1是读取数据的I / O块,最多限制为50个任务。它读取数据和一些元数据。然后他们被传递到第二个街区。如果消息再次进入第一个块,则第二个块决定元数据。因此,在元数据符合条件和短暂等待之后,数据应再次返回到I / O块。第二块MaxDegreeOfParallelism可以是无限的。

现在我注意到当我向I / O块发送大量数据时,需要很长时间才能将消息链接到第二个块。链接数据需要10分钟,而且它们都是一堆发送的。在几秒钟内就像1000个条目。 通常我会像这样实现它:

public void Start()
{
    _ioBlock = new TransformBlock<Data,Tuple<Data, MetaData>>(async data =>
    {
        var metaData = await ReadAsync(data).ConfigureAwait(false);

        return new Tuple<Data, MetaData>(data, metaData);

    }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 50 });

    _waitBlock = new TransformBlock<Tuple<Data, MetaData>,Data>(async dataMetaData =>
    {
        var data = dataMetaData.Item1;
        var metaData = dataMetaData.Item2;

        if (!metaData.Repost)
        {
            return null;
        }

        await Task.Delay(TimeSpan.FromMinutes(1)).ConfigureAwait(false);

        return data;

    }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded });

    _ioBlock.LinkTo(_waitBlock);
    _waitBlock.LinkTo(_ioBlock, data => data != null);
    _waitBlock.LinkTo(DataflowBlock.NullTarget<Data>());

    foreach (var data in Enumerable.Range(0, 2000).Select(i => new Data(i)))
    {
        _ioBlock.Post(data);
    }
}

但是由于所描述的问题,我必须这样实现它:

public void Start()
{
    _ioBlock = new ActionBlock<Data>(async data =>
    {
        var metaData = await ReadAsync(data).ConfigureAwait(false);

        var dataMetaData= new Tuple<Data, MetaData>(data, metaData);

        _waitBlock.Post(dataMetaData);

    }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 50 });

    _waitBlock = new ActionBlock<Tuple<Data, MetaData>>(async dataMetaData =>
    {
        var data = dataMetaData.Item1;
        var metaData = dataMetaData.Item2;

        if (metaData.Repost)
        {
            await Task.Delay(TimeSpan.FromMinutes(1)).ConfigureAwait(false);

            _ioBlock.Post(data);
        }
    }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded });

    foreach (var data in Enumerable.Range(0, 2000).Select(i => new Data(i)))
    {
        _ioBlock.Post(data);
    }
}

当我使用第二种方法时,数据会更快地链接/发布(逐个)。但这对我来说更像是一种黑客攻击。有人知道如何解决这个问题吗?有些朋友建议我使用TPL Pipeline,但对我来说似乎要复杂得多。

1 个答案:

答案 0 :(得分:1)

问题解决了。你需要设置

  

ExecutionDataflowBlockOptions.EnsureOrdered

将数据立即转发到下一个/等待块。

更多信息:

The GNU Multiple Precision Arithmetic Library