繁体   English   中英

TPL数据流和下游块中的异常处理

[英]TPL Dataflow and exception handling in downstream blocks

我有以下伪代码:

var queue = new BufferBlock<int>(new DataflowBlockOptions { BoundedCapacity = 5 });
var a = new ActionBlock<int>(async item =>
    {
        await Task.Delay(500);
        Trace.TraceInformation(
            $"Target 1: | Type: {typeof(int).Name} | Thread: {Thread.CurrentThread.ManagedThreadId} | Message: {item}");
        // handling some logic but it throws
        if (item >= 5) throw new Exception("Something bad happened");

    }, new ExecutionDataflowBlockOptions { BoundedCapacity = 1, MaxDegreeOfParallelism = 1 });

queue.LinkTo(a, new DataflowLinkOptions { PropagateCompletion = true });

var targets = new List<ITargetBlock<int>> {queue};

var broadcaster = new ActionBlock<int>(
    async item =>
    {
        var processingTasks = targets.Select(async t =>
        {
            try
            {
                // This is condition is always false
                // t (bufferblock) has no exceptions. Exception is raised in downstream action block where it sends to
                if (!await t.SendAsync(item))
                    await t.Completion;
            }
            catch (Exception e)
            {
                Trace.TraceInformation("Handled exception : " + e.Message);
            }
        });

        try
        {
            // Neither here the exception is rethrowed
            await Task.WhenAll(processingTasks);
        }
        catch (Exception e)
        {
            Trace.TraceInformation("Handled exception WhenAll : " + e.Message);
        }
    });

for (var i = 1; i <= 10; i++)
{
    broadcaster.Post(i);
}

管道的配置类似于ActionBlock<int> => BufferBlock<int> => ActionBlock<int>

最后一个ActionBlock<int>引发异常,但不会将其重新抛出到我想处理它的源代码块中。

如何重写此代码,以便正确处理异常?

您可以在此处找到有关此主题的官方指南。 总体解决方案是预订所有块Completion任务并检查其状态,并在有需要的情况下更换有故障的块(一个人也应存储该块的所有引用)。 请参考全文以获取更多信息。

具有Faulted块的网络的行为

  1. 预留留言
    为了避免消息损坏,出现故障的块应清除其消息队列,并尽快进入Faulted状态。 有一个不符合此规则的方案: 源块保存由target保留的消息 如果遇到内部异常的块具有目标保留的消息,则不得删除保留的消息,并且在释放或使用该消息之前,不得将该块移入Faulted状态。

  2. 悬挂式网络
    ...

    • 保留对网络中所有块的引用,并使用Task.WaitAllTask.WhenAll等待它们(同步或异步)。 如果一个块发生故障,其Completion任务将在“ Faulted状态下完成。
    • 构建线性网络时,将DataflowLinkOptionsPropagateCompletion == true一起使用。 这将把块完成从源传播到目标。 在这种情况下,等待网络叶子块就足够了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM