OperationCanceledException, созданное в блоке потока данных tpl, проглатывается

По какой-то причине, когда OperationCanceledException выбрасывается внутри IDataflowBlock, блок не распространяет это исключение на свою задачу IDataflowBlock.Completion. Выполнение приведенного ниже примера кода возвращает неожиданную ошибку IDataflowBlock.Completion.Status == TaskStatus.RanToCompletion.

Однако, если тип сгенерированного исключения в блоке изменен на ArgumentNullException, IDataflowBlock.Completion.Status изменится на TaskStatus.Faulted, и исключение будет сохранено в его свойстве InnerException.

Есть идеи, почему OperationCanceledException проглатывают?

[TestFixture]
public class TplDataBlockExceptionTest
{
    [Test]
    public void ShouldThrowException()
    {
        // Arrange
        var block = new TransformBlock<int, string>(i =>
        {
            throw new OperationCanceledException();
            return i.ToString();
        });

        // Act

        block.Post(1);
        block.Complete();

        try
        {
            block.Completion.Wait();
        }
        catch (Exception)
        {
            // ignored
        }

        // Assert

        Assert.That(block.Completion.IsFaulted);
    }
}

person Leor Greenberger    schedule 13.05.2016    source источник


Ответы (1)


Мне удалось связаться со Стивеном Тубом из Microsoft, и он подтвердил, что такое поведение является преднамеренным:

https://github.com/dotnet/corefx/blob/master/src/System.Threading.Tasks.Dataflow/src/Blocks/TransformBlock.cs#L186-L190

https://github.com/dotnet/corefx/blob/master/src/System.Threading.Tasks.Dataflow/src/Internal/Common.cs#L152-L175

person Leor Greenberger    schedule 16.05.2016
comment
Следует отметить, что такое поведение особенно проблематично при работе с классом HttpClient, который выдает TaskCanceledException вместо TimeoutException по какой-то несвязанной причине. - person Theodor Zoulias; 26.06.2020