簡體   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