Tom*_*uλa 3 c# exception-handling task-parallel-library tpl-dataflow
我有以下伪代码:
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);
}
Run Code Online (Sandbox Code Playgroud)
这样配置管道ActionBlock<int> => BufferBlock<int> => ActionBlock<int>。
最后一个ActionBlock<int>抛出异常,但是它不会重新抛出到我想处理它的源代码块中。
如何重写此代码,以便正确处理异常?
您可以在此处找到有关此主题的官方指南。总体解决方案是预订所有块Completion任务并检查其状态,并在需要的情况下更换有故障的块(一个块也应存储所有参考)。请参考全文以获取更多信息。
具有
Faulted块的网络的行为
保留的消息
为了避免消息损坏,出现故障的块应清除其消息队列并尽快进入Faulted状态。有一个不遵循此规则的方案:源块保存由target保留的消息。如果遇到内部异常的块具有目标保留的消息,则不得删除保留的消息,并且在Faulted释放或使用该消息之前,不得将该块移入状态。吊网
...
- 保留对网络中所有块的引用,并使用
Task.WaitAll或Task.WhenAll等待它们(同步或异步)。如果块发生故障,其Completion任务将在该Faulted状态下完成。- 使用
DataflowLinkOptions与PropagateCompletion == true构建线性网络时。这将把块完成从源传播到目标。在这种情况下,等待网络叶子块就足够了。
| 归档时间: |
|
| 查看次数: |
2025 次 |
| 最近记录: |