DataflowBlock.Complete() предположительно останавливает блок от создания большего количества сообщений, что происходит с элементами очереди?

В документации .Complete() говорится следующее:

Сигналы IDataflowBlock о том, что он не должен больше ни принимать, ни создавать сообщения, ни потреблять какие-либо отложенные сообщения.

Итак, скажем, у меня есть BatchedJoinBlock, который я хочу завершить, когда его исходный блок завершится, но я не могу распространять, потому что ссылки находятся на предикатах:

block1.LinkTo(block2.Target1, predicate);
block1.LinkTo(block2.Target2, !predicate);

await block1.Completion;
block2.Complete();

Итак, согласно документации, последняя строка остановит block2 создание новых сообщений, но проблема в том, что block1 завершается, как только block2 принимает все свои сообщения, но эти принятые сообщения могут быть еще не обработаны, так что же произойдет с ними, если block2 не может создавать новые сообщения?

Возможно, я неправильно истолковываю генерировать больше сообщений?


person Luis Ferrao    schedule 30.06.2015    source источник
comment
Ваш пример будет заблокирован, пока вы ждете block1.Completion, но вы не сигнализируете о завершении с помощью block.Complete.   -  person i3arnon    schedule 30.06.2015


Ответы (1)


Complete означает, что блок перестанет принимать больше сообщений, но он будет обрабатывать сообщения, находящиеся в его InputQueue, даже если это приведет к отправке сообщений вперед в конвейере (в отличие от случая, когда блок выходит из строя из-за исключение).

Вы можете увидеть это на этом простом примере:

var transformBlock = new TransformBlock<int, int>(async _ =>
{
    await Task.Delay(100);
    return _;
});

var actionBlock = new ActionBlock<int>(_ => Console.WriteLine(_));
transformBlock.LinkTo(actionBlock);

for (int i = 0; i < 1000; i++)
{
    await transformBlock.SendAsync(i);
}

transformBlock.Complete();
Console.WriteLine("complete");
await transformBlock.Completion;
Console.WriteLine("completed");

complete будет записано немедленно, но TransformBlock продолжит обработку сообщений и медленно переместит их к следующему ActionBlock.


Я тоже не совсем понимаю, что на самом деле означает "больше сообщений". Я предполагаю, что это относится к блокам, которые создают сообщения, а не к тем, которые обрабатывают входящие сообщения, хотя я не могу придумать ни одного.

person i3arnon    schedule 30.06.2015
comment
Complete определяется в IDataflowBlock, который включен для всех типов блоков, поэтому в документации упоминается отправка и получение. - person Guvante; 08.07.2015
comment
@Guvante Как вы можете видеть в примере, TransformBlock продолжает отправлять сообщения после вызова Complete. - person i3arnon; 08.07.2015