C# 以无限并行性多次运行同一ActionBlock
我正在学习第三方物流数据流,我通过一些朋友看到了它的威力,我的实现遇到了问题 我想要/需要的是尽可能快地发送消息。我正在LinqPad中进行一些原型设计,这是我迄今为止所做的: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
// 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如果你知道答案,那么把它贴出来,我会很高兴看到的。