C# TPL数据流如何与“同步”;“全球”;数据

C# TPL数据流如何与“同步”;“全球”;数据,c#,task-parallel-library,software-design,tpl-dataflow,dataflow,C#,Task Parallel Library,Software Design,Tpl Dataflow,Dataflow,我实际上在学习第三方物流数据流。每当我读到关于它的文章时,我觉得ok听起来很棒,但我经常问自己:“好吧,如果我有一个经理,负责不同的会议呢。这些会话可以通过某些消息进行更新。对于复杂的TPL数据流网格,我必须构建用于访问管理器的同步机制,这将减慢或阻塞网格。” 对TPL数据流使用管理对象感觉有点错误 有谁能给我一些提示(链接、书籍、示例…)来说明“正确”的方向,如何解决上述示例。这是一个非常宽泛的问题,没有一些代码。但通常你要么传递一些“状态”“对象为 tuple < /Calp>S或一些DTO

我实际上在学习第三方物流数据流。每当我读到关于它的文章时,我觉得ok听起来很棒,但我经常问自己:“好吧,如果我有一个经理,负责不同的会议呢。这些会话可以通过某些消息进行更新。对于复杂的TPL数据流网格,我必须构建用于访问管理器的同步机制,这将减慢或阻塞网格。”

对TPL数据流使用管理对象感觉有点错误


有谁能给我一些提示(链接、书籍、示例…)来说明“正确”的方向,如何解决上述示例。

这是一个非常宽泛的问题,没有一些代码。但通常你要么传递一些“状态”“对象为<代码> tuple < /Calp>S或一些DTO,我个人认为这是泄漏设计,或者您可以将一些块注入到管道中。

例如,您可以创建一个会话,为它提供一个会话值,该值对于每个管道都是唯一的,并且只需将执行期间发生的新事件通知它的值即可。如果您为不同的会话创建管道,这可能是一个选项,但如果您有一个大管道,则需要另一种方法

例如,您有一个,一个执行会话更新,另一个继续正常的管道执行。在这种情况下,您可以做的是引入一个,将其与动作块和变换块链接。现在用谓词将缓冲区链接到广播块,然后直接将缓冲区链接到转换块

这里的想法是,如果您的消息被过滤(因此需要会话更新),它将进入广播块,然后进入会话更新操作和正常执行管道。如果它与谓词不匹配,则只需遍历您的正常工作流即可

PS:如果这在文字上太复杂,我可以为这种场景提供一些示例代码

var linkOptions=newdataflowlinkoptions{PropagateCompletion=true};
var buffer=new BufferBlock();
//根据构造函数的lambda进行广播并复制
//若您为消息提供了相同的引用,请确保您的访问是线程安全的
var广播=新广播块(i=>i);
链接到(广播,链接选项);
//会话更新块
var sessionUpdate=新操作块(i=>
{
Sleep(newrandom().Next(1000));
WriteLine($“会话更新:{i}”);
},新的ExecutionDataflowBlockOptions{MaxDegreeOfParallelism=4});
//正常执行
变量转换=新的转换块(i=>
{
Sleep(newrandom().Next(1000));
WriteLine($“正常执行:{i}”);
返回i;
},新的ExecutionDataflowBlockOptions{MaxDegreeOfParallelism=4});
//不要完成独立会话块
//仅当乘数为3时才接受消息
LinkTo(sessionUpdate,i=>i%3==0);
//具有完工传播的正规管道
broadcast.LinkTo(转换、链接选项);
对于(变量i=0;i<10;++i)
{
//异步消息
wait buffer.SendAsync(i);
}
buffer.Complete();
等待转变。完成;

thx了解您的详细答案。如果不是太多的工作,一些示例代码会很好。
var linkOptions = new DataflowLinkOptions { PropagateCompletion = true };

var buffer = new BufferBlock<int>();
// broadcast do copy according lambda from constructor
// if you provide same reference for message, make sure that your access is thread-safe
var broadcast = new BroadcastBlock<int>(i => i);
buffer.LinkTo(broadcast, linkOptions);

// session update block
var sessionUpdate = new ActionBlock<int>(i =>
    {
        Thread.Sleep(new Random().Next(1000));
        Console.WriteLine($"Session update:{i}");
    }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 4 });
// normal execution
var transform = new TransformBlock<int, int>(i =>
    {
        Thread.Sleep(new Random().Next(1000));
        Console.WriteLine($"Normal execution:{i}");
        return i;
    }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 4 });
// do not complete the standalone session block
// message will be accepted only for multipliers of 3
broadcast.LinkTo(sessionUpdate, i => i % 3 == 0);
// normal pipeline with completion propagation
broadcast.LinkTo(transform, linkOptions);

for (var i = 0; i < 10; ++i)
{
    // async message
    await buffer.SendAsync(i);
}
buffer.Complete();
await transform.Completion;