了解ActionBlock

时间:2017-11-04 20:06:30

标签: c# task tpl-dataflow

有人可以解释为什么第一个代码块会在我们等待动作块完成时抛出而第二个代码块没有?数据流块没有任何链接,因此不需要传播。

ActionBlock定义1:

ActionBlock<int> workerBlock = new ActionBlock<int>(async (i) =>
{
    await Task.Delay(1);
    throw new OperationCanceledException();
});

ActionBlock定义2:

ActionBlock<int> workerBlock = new ActionBlock<int>(async (i) =>
{
    await ExceptionThrower1();
});


private static async Task ExceptionThrower1()
{
    CancellationTokenSource source= new CancellationTokenSource();
    source.CancelAfter(100);
    await ExceptionThrower2(source.Token);
}

private static async Task ExceptionThrower2(CancellationToken token)
{
    await Task.Delay(1000);
    try
    {
        token.ThrowIfCancellationRequested();
    }
    catch (OperationCanceledException e)
    {
        Console.WriteLine(e);
        throw;
    }
}

测试程序:

workerBlock.SendAsync(1).GetAwaiter().GetResult();
workerBlock.SendAsync(1).GetAwaiter().GetResult();
workerBlock.SendAsync(1).GetAwaiter().GetResult();

workerBlock.Complete();
workerBlock.Completion.GetAwaiter().GetResult();
Console.WriteLine("Done");

如果我使用第一个定义,则“完成”不会被打印,因为等待完成会抛出异常。在第二个定义中,“完成”被打印,但我可以看到ExceptionThrower2中打印出的异常。

根据这篇博文 - https://blogs.msdn.microsoft.com/pfxteam/2011/11/09/exception-handling-in-tpl-dataflow-networks/,即使第二个应该被考虑和未处理的异常,并在完成时被抛出?

2 个答案:

答案 0 :(得分:0)

尝试

ActionBlock<int> workerBlock = new ActionBlock<int>((i) =>
{
    ExceptionThrower1().Wait();
});

ActionBlock已处理异步内容;添加额外的图层似乎吞没了你的异常。

答案 1 :(得分:0)

我无法复制你描述的行为,在我的情况下&#34;完成&#34;每次打印。但是,OperationCanceledException属于&#34;表示合作取消的例外&#34;查看Exception Handling (Task Parallel Library)并搜索OperationCanceledException。