C# 以无限并行性多次运行同一ActionBlock

C# 以无限并行性多次运行同一ActionBlock,c#,multithreading,task-parallel-library,tpl-dataflow,C#,Multithreading,Task Parallel Library,Tpl Dataflow,我正在学习第三方物流数据流,我通过一些朋友看到了它的威力,我的实现遇到了问题 我想要/需要的是尽可能快地发送消息。我正在LinqPad中进行一些原型设计,这是我迄今为止所做的: // Holds all the messages for my loadMessage ActionBlock to grab its data from var bufferBlock = new BufferBlock<string>(); // Sends message to where it n

我正在学习第三方物流数据流,我通过一些朋友看到了它的威力,我的实现遇到了问题

我想要/需要的是尽可能快地发送消息。我正在LinqPad中进行一些原型设计,这是我迄今为止所做的:

// Holds all the messages for my loadMessage ActionBlock to grab its data from
var bufferBlock = new BufferBlock<string>();

// Sends message to where it needs to go as fast as it can.
var loadMessage = new ActionBlock<string>(msg => 
{
    msg.Dump();
},  
new ExecutionDataflowBlockOptions
{
    MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded
});

// Links the blocks together
bufferBlock.LinkTo(loadMessage);

// Loads the Buffer
for (int i = 0; i < 10; i++)
{
    bufferBlock.Post("This is a message");
}

//Calls completion to stop threads
bufferBlock.Complete();
loadMessage.Complete(); 
//保存my loadMessage ActionBlock的所有消息,以便从中获取其数据
var bufferBlock=新的bufferBlock();
//将消息以最快的速度发送到需要的位置。
var loadMessage=new ActionBlock(消息=>
{
msg.Dump();
},  
新的ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism=DataflowBlockOptions.Unbounded
});
//将块链接在一起
bufferBlock.LinkTo(加载消息);
//加载缓冲区
对于(int i=0;i<10;i++)
{
Post(“这是一条消息”);
}
//调用完成来停止线程
bufferBlock.Complete();
loadMessage.Complete();
问题是loadMessageBlock没有转储上面示例中的消息。我一直在寻找一些运气不佳的见解。我想我遗漏了第三方物流的一些基本要素。我的理解是,BufferBlock保存其他块要处理的信息,ActionBlocked(链接到BufferBlock)应该从缓冲区抓取数据并执行它需要执行的操作。在将信息放入缓冲区的For循环停止后,将调用completion来停止线程

在我的实现中,我有一个并行程序,它可以在我的loadMessage中运行代码。我只是不能实现TPL来做我想做的事情,我的理解是TPL将比Parallel.For更快

我认为这是怎么回事,我离这里很远吗?我是否误用了第三方物流?我将继续寻找答案,任何指点都将受到高度赞赏。谢谢

  • 我想要/需要的是尽可能快地发送消息:

    要实现这一点,您需要并发地向缓冲区块和从缓冲区块发送/接收数据。以下是片段:

    var bufferBlock = new BufferBlock<string>();
    // Write to and read from the message block concurrently. 
    var post01 = Task.Run(() =>
    {
        // Loads the Buffer
        for (int i = 0; i < 10; i++)
        {
            bufferBlock.Post(string.Format("This is a message {0}",i));
        }
    });
    var receive = Task.Run(() =>
    {
        for (int i = 0; i < 10; i++)
        {
            var message = bufferBlock.Receive();
            message.Dump();
        }
    });
    
    
    Task.WaitAll(post01, receive);
    
    var bufferBlock=new bufferBlock();
    //同时写入和读取消息块。
    var post01=Task.Run(()=>
    {
    //加载缓冲区
    对于(int i=0;i<10;i++)
    {
    Post(string.Format(“这是一条消息{0}”,i));
    }
    });
    var receive=Task.Run(()=>
    {
    对于(int i=0;i<10;i++)
    {
    var message=bufferBlock.Receive();
    message.Dump();
    }
    });
    Task.WaitAll(post01,receive);
    
    更多关于这方面的信息,请参见

  • 我的理解是,第三方物流将比平行物流更快

    这是不正确的,因为它们使用相同的底层结构。它们属于同一名称空间


  • 首先,请注意术语:TPL(Task Parallel Library的缩写)与TPL Dataflow不同,它只是一个子集。TPL作为一个整体包括
    Parallel.For()
    Task
    类型

    现在,您的代码的问题是您太快完成了
    loadMessage
    块。调用
    Complete()
    后,块将不再接受任何消息,因此您发布到
    bufferBlock
    的消息将永远不会到达
    loadMessage

    您需要的是,只有在
    bufferBlock
    将其所有消息发送给它之后,才能完成
    loadMessage
    。这正是
    所做的:

    bufferBlock.LinkTo(
        loadMessage, new DataflowLinkOptions { PropagateCompletion = true });
    
    // post your data to bufferBlock here
    
    bufferBlock.Complete();
    await loadMessage.Completion;
    
    此外,在这种特定情况下,根本不需要
    缓冲块
    ,您可以直接将消息发布到
    加载消息

    我的理解是,第三方物流将比平行物流更快


    我不明白为什么总的来说应该更快。在正常情况下,他们的表现应该是可比的。因此,你应该使用一个更适合你的问题,而不是选择一个,因为“它更快”。如果您真的那么关心性能,那么请编写两种方式的代码,并衡量哪种方式更好。

    谢谢您的帮助。我并没有在这个特殊的案例中使用TPL,但我正在阅读更多关于任务和线程的内容,以便将来实现。这里不需要使用
    Task
    来接收,这正是
    ActionBlock
    的目的。@svick无论您选择什么方式都可以,即使在我发布的MSDN链接的示例中,他们也使用Task。没有理由说吃面包比吃米饭好@对Annguyen来说,问题是“为什么这个代码不起作用?”你的答案几乎是:“我不知道,但是这个完全不同的代码起作用”。我认为这不是一个好答案。@svick如果你知道答案,那么把它贴出来,我会很高兴看到的。