Как избежать использования ActionBlock <TInput>.Post, когда PostDataflowBlockOptions.BoundedCapacity не является значением по умолчанию? - PullRequest
1 голос
/ 26 мая 2020

Я слышал, что вы можете потерять информацию, если используете метод Post вместо метода SendAsync объекта ActionBlock<T>, когда вы решите использовать его свойство BoundedCapacity.

Может кто-нибудь объяснить, почему это так?

Ответы [ 2 ]

2 голосов
/ 26 мая 2020

Метод Post пытается синхронно опубликовать элемент и возвращает true или false, в зависимости от того, принял ли элемент блок или нет. Причины не принимать элемент:

  1. Блок помечается как завершенный (путем вызова его метода Complete).
  2. Блок завершен, успешно или неуспешно (его Completion.IsCompleted свойство возвращает true).
  3. Блок имеет ограниченную емкость (опция BoundedCapacity != -1), и его буфер в настоящее время заполнен.

Метод SendAsync пытается опубликовать элемент асинхронно и возвращает Task<bool>. Эта задача всегда будет завершена, если только блок не имеет ограниченной емкости, его буфер в настоящее время заполнен, и он в настоящее время не завершен или не отмечен как завершенный. Это единственный случай, когда SendAsync будет вести себя асинхронно. После ожидания задачи результат задачи bool указывает, принял ли блок элемент или нет. Причины не принимать элемент:

  1. Блок был помечен как завершенный либо до вызова SendAsync, либо во время ожидания.
  2. Блок был завершен либо до вызова SendAsync, или во время ожидания в результате исключения, или потому что был вызван его метод Fault.

Итак, разница между Post и SendAsync это точка (3). Они ведут себя по-другому в случае блока ограниченной емкости с полным буфером. В этом случае Post немедленно отклоняет элемент, в то время как SendAsync примет его асинхронно, когда в буфере снова появится свободное место.

В большинстве случаев поведение SendAsync является желательным. Использование Post вместо SendAsync может рассматриваться как ожидаемая ошибка, когда спустя некоторое время блок переконфигурируется как ограниченный, чтобы решить недавно обнаруженные проблемы, связанные с чрезмерным использованием памяти.

Рекомендуется не отклонять возвращаемое значение обоих методов, потому что возвращаемое значение 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 голосов
/ 26 мая 2020

Да, вы можете потерять информацию, Post имеет более высокий потенциал, но SendAsync также может потерять информацию. Допустим, у вас есть ActionBlock, на выполнение которого требуется 1000 мс, в течение этого периода времени отправляется 10 сообщений. BoundedCapacity имеет значение 5 для ActionBlock. В результате последние 5 сообщений не обрабатываются, информация теряется.

Вот некоторые подробности об этом: TPL Dataflow, в чем функциональная разница между Post () и SendAsyn c ()?

См. Второй ответ.

...