当 PostDataflowBlockOptions.BoundedCapacity 不是默认值时避免使用 ActionBlock<TInput>.Post?

Avoiding use of ActionBlock<TInput>.Post when PostDataflowBlockOptions.BoundedCapacity is not the default value?

我听说如果您使用 Post 方法而不是 ActionBlock<T> 对象的 SendAsync 方法,您可能会丢失信息,当您决定使用它时 BoundedCapacity 属性.

有人可以解释为什么会这样吗?

是的,您可能会丢失信息,Post 更有可能做到这一点,但 SendAsync 也可能会丢失信息。假设您有一个需要 1000 毫秒才能完成的 ActionBlock,在此期间发布了 10 条消息。对于 ActionBlockBoundedCapacity 设置为 5。结果最后5条消息没有处理,信息丢失。

这里有一些细节: TPL Dataflow, whats the functional difference between Post() and SendAsync()?

查看第二个答案。

Post 方法尝试 post 一个项目同步 returns truefalse,取决于块是否接受了项目或不是。不接受项目的原因:

  1. 该块被标记为已完成(通过调用其 Complete 方法)。
  2. 块已完成,无论是成功还是失败(其 Completion.IsCompleted 属性 returns true)。
  3. 该块具有有限容量(选项BoundedCapacity != -1),其缓冲区当前已满。

SendAsync 方法尝试异步地 post 一个项目并且 return 是一个 Task<bool>。此任务将始终完成,除非该块具有有限容量,其缓冲区当前已满,并且当前未完成或未标记为已完成。这是 SendAsync 异步行为的唯一情况。等待任务后,任务的 bool 结果表明方块是否接受了物品。不接受项目的原因:

  1. 块在调用 SendAsync 之前或在等待期间被标记为已完成。
  2. 块在调用 SendAsync 之前完成,或者在等待期间由于异常而完成,或者因为它的 Fault 方法被调用。

所以PostSendAsync的区别就是第(3)点。在具有完整缓冲区的有限容量块的情况下,它们的行为不同。在这种情况下,Post 立即拒绝该项目,而 SendAsync 将在缓冲区再次空闲 space 时异步接受它。

在大多数情况下,SendAsync 的行为是可取的。使用 Post 而不是 SendAsync 可以看作是等待发生的错误,一段时间后块被重新配置为有界,以解决新发现的与过度内存使用相关的问题。

最好不要忽略这两种方法的 return 值,因为 false 的 return 值在大多数情况下表示存在错误。很少有人期望并准备好处理 false 结果。一些想法:

if (!block.Post(item)) throw new InvalidOperationException();

if (!await block.SendAsync(item)) throw new InvalidOperationException();

var accepted = block.Post(item); Debug.Assert(accepted);

var accepted = await block.SendAsync(item); Debug.Assert(accepted);