当 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 条消息。对于 ActionBlock
,BoundedCapacity
设置为 5。结果最后5条消息没有处理,信息丢失。
这里有一些细节:
TPL Dataflow, whats the functional difference between Post() and SendAsync()?
查看第二个答案。
Post
方法尝试 post 一个项目同步 returns true
或 false
,取决于块是否接受了项目或不是。不接受项目的原因:
- 该块被标记为已完成(通过调用其
Complete
方法)。
- 块已完成,无论是成功还是失败(其
Completion.IsCompleted
属性 returns true
)。
- 该块具有有限容量(选项
BoundedCapacity != -1
),其缓冲区当前已满。
SendAsync
方法尝试异步地 post 一个项目并且 return 是一个 Task<bool>
。此任务将始终完成,除非该块具有有限容量,其缓冲区当前已满,并且当前未完成或未标记为已完成。这是 SendAsync
异步行为的唯一情况。等待任务后,任务的 bool
结果表明方块是否接受了物品。不接受项目的原因:
- 块在调用
SendAsync
之前或在等待期间被标记为已完成。
- 块在调用
SendAsync
之前完成,或者在等待期间由于异常而完成,或者因为它的 Fault
方法被调用。
所以Post
和SendAsync
的区别就是第(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);
我听说如果您使用 Post
方法而不是 ActionBlock<T>
对象的 SendAsync
方法,您可能会丢失信息,当您决定使用它时 BoundedCapacity
属性.
有人可以解释为什么会这样吗?
是的,您可能会丢失信息,Post
更有可能做到这一点,但 SendAsync
也可能会丢失信息。假设您有一个需要 1000 毫秒才能完成的 ActionBlock,在此期间发布了 10 条消息。对于 ActionBlock
,BoundedCapacity
设置为 5。结果最后5条消息没有处理,信息丢失。
这里有一些细节: TPL Dataflow, whats the functional difference between Post() and SendAsync()?
查看第二个答案。
Post
方法尝试 post 一个项目同步 returns true
或 false
,取决于块是否接受了项目或不是。不接受项目的原因:
- 该块被标记为已完成(通过调用其
Complete
方法)。 - 块已完成,无论是成功还是失败(其
Completion.IsCompleted
属性 returnstrue
)。 - 该块具有有限容量(选项
BoundedCapacity != -1
),其缓冲区当前已满。
SendAsync
方法尝试异步地 post 一个项目并且 return 是一个 Task<bool>
。此任务将始终完成,除非该块具有有限容量,其缓冲区当前已满,并且当前未完成或未标记为已完成。这是 SendAsync
异步行为的唯一情况。等待任务后,任务的 bool
结果表明方块是否接受了物品。不接受项目的原因:
- 块在调用
SendAsync
之前或在等待期间被标记为已完成。 - 块在调用
SendAsync
之前完成,或者在等待期间由于异常而完成,或者因为它的Fault
方法被调用。
所以Post
和SendAsync
的区别就是第(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);