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

问题描述 投票:0回答:1

我听说,如果你使用的是 Post 方法,而不是 SendAsync 办法 ActionBlock<T> 对象,当你决定利用它的 BoundedCapacity 财产。

谁能解释一下为什么会这样?

c# asynchronous .net-core async-await dataflow
1个回答
2
投票

Post 方法试图同步发布一个项目,并返回 truefalse,取决于该区块是否接受该项目。不接受一个项目的原因。

  1. 块被标记为已完成(通过调用它的 Complete 方法)。)
  2. 该块完成了,要么成功,要么不成功(其 Completion.IsCompleted 属性返回 true).
  3. 块的容量是有界的(选项 BoundedCapacity != -1),其缓冲区目前已满。

缓冲区的 SendAsync 方法试图异步发布一个项目并返回一个 Task<bool>. 这个任务总是会被完成,除非该块的容量是有边界的,它的缓冲区当前是满的,而且它当前没有完成或标记为完成。只有在这种情况下,才会出现 SendAsync 将会异步行事。在等待任务后, bool 任务的结果表示该块是否接受该项目。不接受某项的原因。

  1. 块被标记为已完成,或者是在调用... SendAsync,或在等待期间。
  2. 该区块的完成,要么是在调用 SendAsync在等待过程中,或由于异常情况,或由于它的 Fault 方法被调用。

所以 PostSendAsync 是点(3)。在有界容量的块和满缓冲区的情况下,它们的表现是不同的。在这种情况下 Post 立即拒绝该项目,而 SendAsync 将会在缓冲区再次有空闲空间时异步接受它。

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

最好不要否定这两个方法的返回值,因为返回值为 false 在大多数情况下,它表明一个错误。很少有期望并准备处理一个 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);

2
投票

是的,你可以失去信息。Post 潜力较大,但 SendAsync 也会丢失信息。假设你有一个ActionBlock需要1000毫秒才能完成,在这个时间段内有10条消息被发布。BoundedCapacity 被设置为5的 ActionBlock. 结果,最后5条信息没有处理,信息丢失。

下面是一些细节。TPL数据流,Post()和SendAsync()在功能上有什么区别?

请看第二个答案。

© www.soinside.com 2019 - 2024. All rights reserved.