Я разрабатываю долгосрочный конвейер потока данных, состоящий из нескольких блоков. Элементы подаются во входной блок конвейера, в конечном итоге проходят через него и отображаются в пользовательском интерфейсе в конце (в знак любезности для пользователя - настоящая задача конвейера - сохранять результаты обработки на диск).
Лямбда-функции внутри блоков конвейера могут вызывать исключения по разным причинам (неправильный ввод, сбой сети, ошибка во время вычислений и т. Д.). В этом случае, вместо того, чтобы отказываться от всего конвейера, я хотел бы исключить проблемный элемент и отобразить его в пользовательском интерфейсе в разделе «Ошибки».
Как лучше всего это сделать? Я понимаю, что могу обернуть каждую лямбда-функцию в try / catch:
var errorLoggingBlock = new ActionBlock<Tuple<WorkItem, Exception>>(...)
var workerBlock = new TransformBlock<WorkItem, WorkItem>(item =>
{
try {
return DoStuff(item);
} catch (Exception ex) {
errorLoggingBlock.SendAsync(Tuple.Create(item, ex));
return null;
}
}
Но у меня в конвейере около 10 блоков, и копировать / вставлять этот код в каждый кажется глупым. Кроме того, мне не нравится идея возврата null, так как теперь все нижележащие блоки должны будут его проверять.
Моя следующая лучшая идея - создать функцию, которая возвращает лямбду, которая будет обертывать за меня:
private Func<TArg, TResult> HandleErrors<TArg, TResult>(Func<TArg, TResult> f) where TArg:WorkItem
{
return arg =>
{
try {
return f(arg);
} catch (Exception ex) {
errorLoggingBlock.SendAsync(Tuple.Create(item, ex));
return default(TResult);
}
};
}
Но это кажется слишком мета. Есть ли способ лучше ?
Try
библиотеку Стивена Клири. Он позволяет передавать сообщение через все блоки конвейера, а затем наблюдать за любыми исключениями, которые произошли с этим сообщением в конце. - person Theodor Zoulias   schedule 28.08.2020