TPL Dataflow, whats the functional difference between Post() and SendAsync()?

To see the difference, you need a situation where blocks will postpone their messages. In this case, Post will return false immediately, whereas SendAsync will return a Task that will be completed when the block decides what to do with the message. The Task will have a true result if the message is accepted, and a false result if not.

One example of a postponing situation is a non-greedy join. A simpler example is when you set 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);
}

Leave a Comment