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

本小妞迷上赌 提交于 2020-05-30 08:13:07

问题


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?


回答1:


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:

  1. The block is marked as completed (by calling its Complete method).
  2. The block is completed, either successfully or unsuccessfully (its Completion.IsCompleted property returns true).
  3. The block has a bounded capacity (option BoundedCapacity != -1), and its buffer is currently full.

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:

  1. The block was marked as completed either before calling the SendAsync, or during the awaiting.
  2. The block was completed either before calling the SendAsync, or during the awaiting as a result of an exception, or because its Fault method was invoked.

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.

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.

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);



回答2:


Yes you can lose information, Post has higher potential to do that but SendAsync also can lose information. Let's say you have an ActionBlock that is taking 1000 ms to complete, during this time period 10 messages are posted. BoundedCapacity is set to 5 for the ActionBlock. As a result, the last 5 message is not processed, information lost.

Here are some detail about it: TPL Dataflow, whats the functional difference between Post() and SendAsync()?

See second answer.



来源:https://stackoverflow.com/questions/62016856/avoiding-use-of-actionblocktinput-post-when-postdataflowblockoptions-boundedca

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!