问题描述
我听说如果使用 Post
方法而不是 ActionBlock
的 SendAsync
方法,可能会丢失信息对象,当您决定使用它的 BoundedCapacity
属性时.
I've heard that you can lose information if you use the Post
method instead of the SendAsync
method of an ActionBlock<T>
object, when you decide to utilize it's BoundedCapacity
property.
谁能解释一下为什么会这样?
Could someone please explain why that is so?
推荐答案
Post
方法尝试同步发布项目并返回 true
或 false
,具体取决于关于区块是否接受该项目.不接受项目的原因:
The Post
method attempts to post an item synchronously and returns true
or false
, depending on whether the block accepted the item or not. Reasons to not accept an item:
- 块被标记为完成(通过调用它的
Complete
方法). - 块已完成,无论成功还是失败(其
Completion.IsCompleted
属性返回true
. - 该块具有有界容量(选项
BoundedCapacity != -1
),并且其缓冲区当前已满.
SendAsync
方法尝试异步发布项目并返回 Task
.此任务将始终完成,除非该块具有有限容量,其缓冲区当前已满,并且当前未完成或标记为已完成.这是 SendAsync
将异步运行的唯一情况.等待任务后,任务的bool
结果表明该块是否接受了该项目.不接受项目的原因:
The SendAsync
method attempts to post an item asynchronously and returns a Task<bool>
. This task will always be completed, unless the block has a bounded capacity, its buffer is currently full, and it's not currently completed or marked as completed. This is the only case that the SendAsync
will behave asynchronously. After awaiting the task, the bool
result of the task indicates whether the block accepted the item or not. Reasons to not accept an item:
- 块在调用
SendAsync
之前或在等待期间被标记为已完成. - 块在调用
SendAsync
之前完成,或者在等待期间由于异常,或者因为它的Fault
方法被调用.
- The block was marked as completed either before calling the
SendAsync
, or during the awaiting. - The block was completed either before calling the
SendAsync
, or during the awaiting as a result of an exception, or because itsFault
method was invoked.
所以 Post
和 SendAsync
之间的区别在于点 (3).在具有完整缓冲区的有限容量块的情况下,它们的行为有所不同.在这种情况下,Post
立即拒绝该项目,而 SendAsync
将在缓冲区再次有可用空间时异步接受它.
So the difference between Post
and SendAsync
is the point (3). They behave differently in the case of a bounded-capacity block with a full buffer. In this case the Post
rejects immediately the item, while the SendAsync
will asynchronously accept it when the buffer has free space again.
在大多数情况下,SendAsync
的行为是理想的.使用 Post
而不是 SendAsync
可以看作是一个等待发生的错误,当一段时间后块被重新配置为有界时,以解决新发现的相关问题内存使用过多.
In most cases the behavior of SendAsync
is the desirable one. Using the Post
instead of the SendAsync
can be seen as a bug that is waiting to happen, when some time later the block is reconfigured as bounded, to solve newly discovered problems related with excessive memory usage.
最好不要忽略这两种方法的返回值,因为 false
的返回值在大多数情况下表示存在错误.期望并准备好处理 false
结果是非常罕见的.一些想法:
It is a good idea to not dismiss the return value of both methods, because a return value of false
indicates in most cases a bug. it is quite rare to expect and be ready to handle a false
result. Some ideas:
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);
这篇关于避免使用 ActionBlock<TInput>.Post 当 PostDataflowBlockOptions.BoundedCapacity 不是默认值时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!