TPL DataFlow не может обработать исключение в ActionBlock
Я пытаюсь отправить копию одного сообщения от ActionBlock<int>
для нескольких потребителей, которые также ActionBlock<int>
, Это работает хорошо, однако, если один из целевых блоков выдает исключение, кажется, что это не распространяется на исходный блок. Вот как я пытаюсь обработать исключение, но оно никогда не идет к catch
часть:
static void Main(string[] args)
{
var t1 = new ActionBlock<int>(async i =>
{
await Task.Delay(2000);
Trace.TraceInformation($"target 1 | Thread {System.Threading.Thread.CurrentThread.ManagedThreadId} | message {i}");
}, new ExecutionDataflowBlockOptions { BoundedCapacity = 5 });
var t2 = new ActionBlock<int>(async i =>
{
await Task.Delay(1000);
Trace.TraceInformation($"target 2 | Thread {System.Threading.Thread.CurrentThread.ManagedThreadId} | message {i}");
}, new ExecutionDataflowBlockOptions { BoundedCapacity = 5 });
var t3 = new ActionBlock<int>(async i =>
{
await Task.Delay(100);
Trace.TraceInformation($"target 3 | Thread {System.Threading.Thread.CurrentThread.ManagedThreadId} | message {i}");
if (i > 5)
throw new Exception("Too big number");
}, new ExecutionDataflowBlockOptions { BoundedCapacity = 5 });
var targets = new [] { t1, t2, t3};
var broadcaster = new ActionBlock<int>(
async item =>
{
var processingTasks = targets.Select(async t =>
{
try
{
await t.SendAsync(item);
}
catch
{
Trace.TraceInformation("handled in select"); // never goes here
}
});
try
{
await Task.WhenAll(processingTasks);
}
catch
{
Trace.TraceInformation("handled"); // never goes here
}
});
for (var i = 1; i <= 10; i++)
broadcaster.Post(i);
}
Я не уверен, что мне здесь не хватает, но я хотел бы иметь возможность получить исключение и в каком целевом блоке произошел сбой.
1 ответ
Если блок входит в неисправное состояние, он больше не будет принимать новые элементы и Exception
он бросил будет привязан к его Completion
задание и / или распространяется с его завершением, если связано в конвейере. Соблюдать Exception
вы можете await
завершение, если блок отказывается от большего количества предметов.
var processingTasks = targets.Select(async t =>
{
try
{
if(!await t.SendAsync(item))
await t.Completion;
}
catch
{
Trace.TraceInformation("handled in select"); // never goes here
}
});