将单个结果与多个其他结果连接的数据块

Bor*_*ens 5 .net c# tpl-dataflow

在我的应用程序中,我想将多个字符串与替换值字典连接起来。

readTemplateBlock获取与FileInfos并返回其作为字符串内容喂养。
getReplacersBlock被供给(一次)与单个代用品字典。
joinTemplateAndReplacersBlock应参加的每个项目readTemplateBlock与一个getReplacersBlock结果。

在我当前的设置中,它要求我为我发布的每个文件再次发布相同的替换字典。

// Build
var readTemplateBlock = new TransformBlock<FileInfo, string>(file => File.ReadAllText(file.FullName));
var getReplacersBlock = new WriteOnceBlock<IDictionary<string, string>>(null);
var joinTemplateAndReplacersBlock = new JoinBlock<string, IDictionary<string, string>>();

// Assemble
var propagateComplete = new DataflowLinkOptions {PropagateCompletion = true};

readTemplateBlock.LinkTo(joinTemplateAndReplacersBlock.Target1, propagateComplete);
getReplacersBlock.LinkTo(joinTemplateAndReplacersBlock.Target2, propagateComplete);
joinTemplateAndReplacersBlock.LinkTo(replaceTemplateBlock, propagateComplete);

// Post
foreach (var template in templateFilenames)
{
    getFileBlock.Post(template);
}
getFileBlock.Complete();

getReplacersBlock.Post(replacers);
getReplacersBlock.Complete();
Run Code Online (Sandbox Code Playgroud)

有没有更好的块我错过了?也许我忽略了一个配置选项?

svi*_*ick 3

我无法弄清楚如何使用内置数据流块来做到这一点。我可以看到的替代方案:

\n\n
    \n
  1. 将 aBufferBlock与小号BoundedCapacity一起使用Task,以不断向其发送值。Task获取值的具体方式可能会有所不同,但如果您愿意WriteOnceBlock,您可以重用并封装它:

    \n\n
    static IPropagatorBlock<T, T> CreateWriteOnceRepeaterBlock<T>()\n{\n    var target = new WriteOnceBlock<T>(null);\n    var source = new BufferBlock<T>(new DataflowBlockOptions { BoundedCapacity = 1 });\n\n    Task.Run(\n        async () =>\n        {\n            var value = await target.ReceiveAsync();\n\n            while (true)\n            {\n                await source.SendAsync(value);\n            }\n        });\n\n    return DataflowBlock.Encapsulate(target, source);\n}\n
    Run Code Online (Sandbox Code Playgroud)\n\n

    然后您将使用CreateWriteOnceRepeaterBlock<IDictionary<string, string>>()而不是new WriteOnceBlock<IDictionary<string, string>>(null).

  2. \n
  3. 编写一个与WriteOnceBlock您想要的行为类似的自定义块。看看它的来源WriteOnceBlock有多大,这可能不是很有吸引力。

  4. \n
  5. 为此,请使用 aTaskCompletionSource代替数据流块。

    \n\n

    假设您当前的代码如下所示(System.ValueTuple为简洁起见,使用 C# 7 和包):

    \n\n
    void ReplaceTemplateBlockAction(Tuple<string, IDictionary<string, string>> tuple)\n{\n    var (template, replacers) = tuple;\n    \xe2\x80\xa6\n}\n\n\xe2\x80\xa6\n\nvar getReplacersBlock = new WriteOnceBlock<IDictionary<string, string>>(null);\nvar replaceTemplateBlock = new ActionBlock<Tuple<string, IDictionary<string, string>>>(\n    ReplaceTemplateBlockAction);\n\xe2\x80\xa6\ngetReplacersBlock.Post(replacers);\n
    Run Code Online (Sandbox Code Playgroud)\n\n

    您可以使用:

    \n\n
    void ReplaceTemplateBlockAction(string template, IDictionary<string, string>>> replacers)\n{\n    \xe2\x80\xa6\n}\n\n\xe2\x80\xa6\n\nvar getReplacersTcs = new TaskCompletionSource<IDictionary<string, string>>();\nvar replaceTemplateBlock = new ActionBlock<string>(\n    async template => ReplaceTemplateBlockAction(template, await getReplacersTcs.Task));\n\xe2\x80\xa6\ngetReplacersTcs.SetResult(replacers);\n
    Run Code Online (Sandbox Code Playgroud)
  6. \n
\n