TransformBlock发布到输出

时间:2016-12-01 08:39:19

标签: .net tpl-dataflow

我的情况是,我有BufferBlock<Stream>来自外部来源的Stream,让我们说文件系统或某个FTP服务器。这些文件Stream将传递到另一个块并进行处理。

唯一的问题是其中一些文件是压缩的,我想在中间添加一个Block,它会在必要时解压缩文件,并创建多个输出Stream&#39; s为每个条目。

但我不想使用TransformBlockMany,因为这意味着我必须完全接收ZIP Stream并立即创建输出Stream数组。

我希望只要条目准备好,此Block就会收到ZIP Stream,开始解压缩,Push到下一个流,因此Process Block可以尽快开始处理因为第一个文件已解压缩,而不是等到所有内容都解压缩。

我该怎么做呢?

2 个答案:

答案 0 :(得分:1)

我了解到我的问题无法一起使用yield / async。但在重构​​之后,我摆脱了这种需求,并提出了以下(简化)版本:

var block = new TransformManyBlock<Stream, Stream>((input) => {
var archive = new System.IO.Compression.ZipArchive(input, System.IO.Compression.ZipArchiveMode.Read, true);
foreach (ZipArchiveEntry entry in archive.Entries)
{
    if (string.IsNullOrWhiteSpace(entry.Name)) //is a folder
        continue;

    yield return entry.Open();

}

});

答案 1 :(得分:0)

您可以使用predicate linking块为您的解压缩逻辑设置中间块,以便您可以检查流是否存档,如下所示:

var buffer = new BufferBlock<Stream>();
var unzipper = new TransformManyBlock<Stream, Stream>(input => { /* unzip here */ });
var processBlock = new ActionBlock<Stream>(input => { /* process streams here */ });

buffer.LinkTo(unzipper, input => /* check is stream a zip archive */);
unzipper.LinkTo(processBlock);
buffer.LinkTo(processBlock);

至于asyncyield一起使用,您可以尝试使用GitHubNuGet上提供的AsyncEnumerable个包。