TPL Dataflow,Post()和SendAsync()之间的功能区别是什么?

时间:2012-11-28 06:44:07

标签: c# concurrency task-parallel-library message-passing tpl-dataflow

我对通过Post()或SendAsync()发送项目之间的区别感到困惑。我的理解是,在所有情况下,一旦项目到达数据块的输入缓冲区,控制权将返回到调用上下文,对吗?那为什么我需要SendAsync?如果我的假设不正确,那么我想,相反,如果使用数据块的整个想法是建立并发和异步环境,为什么有人会使用Post()。

我当然理解技术上的区别在于Post()返回一个bool,而SendAsync返回一个等待bool的任务。但是它有什么影响呢?何时返回bool(我理解是否确认该项是否放在数据块的队列中)会被延迟?我理解async / await并发框架的一般概念,但在这里并没有多大意义,因为除了bool之外,对传入项所做的任何操作的结果都不会返回给调用者,而是放在一个“out-queue”,转发到链接数据块或丢弃。

发送项目时两种方法之间是否有任何性能差异?

2 个答案:

答案 0 :(得分:51)

要了解其中的差异,您需要一种情况,即阻止他们的邮件会推迟。在这种情况下,Post会立即返回false,而SendAsync将返回Task,当块决定如何处理该消息时,该Task将完成。如果邮件被接受,则true会产生false结果,否则会产生BoundedCapacity结果。

推迟情况的一个例子是非贪婪的加入。一个更简单的例子是当你设置[TestMethod] public void Post_WhenNotFull_ReturnsTrue() { var block = new BufferBlock<int>(new DataflowBlockOptions {BoundedCapacity = 1}); var result = block.Post(13); Assert.IsTrue(result); } [TestMethod] public void Post_WhenFull_ReturnsFalse() { var block = new BufferBlock<int>(new DataflowBlockOptions { BoundedCapacity = 1 }); block.Post(13); var result = block.Post(13); Assert.IsFalse(result); } [TestMethod] public void SendAsync_WhenNotFull_ReturnsCompleteTask() { // This is an implementation detail; technically, SendAsync could return a task that would complete "quickly" instead of already being completed. var block = new BufferBlock<int>(new DataflowBlockOptions { BoundedCapacity = 1 }); var result = block.SendAsync(13); Assert.IsTrue(result.IsCompleted); } [TestMethod] public void SendAsync_WhenFull_ReturnsIncompleteTask() { var block = new BufferBlock<int>(new DataflowBlockOptions { BoundedCapacity = 1 }); block.Post(13); var result = block.SendAsync(13); Assert.IsFalse(result.IsCompleted); } [TestMethod] public async Task SendAsync_BecomesNotFull_CompletesTaskWithTrueResult() { var block = new BufferBlock<int>(new DataflowBlockOptions { BoundedCapacity = 1 }); block.Post(13); var task = block.SendAsync(13); block.Receive(); var result = await task; Assert.IsTrue(result); } [TestMethod] public async Task SendAsync_BecomesDecliningPermanently_CompletesTaskWithFalseResult() { var block = new BufferBlock<int>(new DataflowBlockOptions { BoundedCapacity = 1 }); block.Post(13); var task = block.SendAsync(13); block.Complete(); var result = await task; Assert.IsFalse(result); }

{{1}}

答案 1 :(得分:14)

文档使IMO明确地说明了这一点。特别是Post

  

一旦目标块决定接受或拒绝该项,此方法将返回,但除非目标块的特殊语义另有规定,否则它不会等待实际处理该项。

  

对于支持推迟提供的消息的目标块,或者可能在Post实现中执行更多处理的块,请考虑使用SendAsync,它将立即返回并使目标能够推迟发布消息,然后在SendAsync返回后使用它。

换句话说,虽然两者在消息的处理方面都是异步的,但SendAsync允许目标块决定是否接受消息也是异步的。

听起来SendAsync通常是“更异步”的方法,而且可能是一般的鼓励方法。 对我来说 p>