CCR: лучшая практика для обработки ошибок с использованием причинно-следственных связей
Имея сложную последовательность задач, реализация обработки ошибок может быстро раздуть код при использовании блоков try/catch и таких вещей, как приемники Choice на PortSet<ActualResult, Exception>
для каждой маленькой задачи.
К счастью, CCR, кажется, предлагает механизм для обработки исключений в более общем виде для графика задач: причинно-следственные связи. Типичный пример выглядит так:
Port<Exception> exceptionPort = new Port<Exception>();
Dispatcher.AddCausality(new Causality("some job", exceptionPort));
Arbiter.Activate(
dispatcherQueue,
Arbiter.Receive(false, exceptionPort, ex => Console.WriteLine(ex)));
// now schedule the real tasks
В моем случае у меня есть вычислительное приложение, использующее CCR для реализации сценария разброса / сбора, разделяющего "задания" на кучу распараллеленных задач. (Кроме того, одновременно может быть запущено более одного из этих заданий.) В случае сбоя одного задания я хочу остановить все оставшиеся задания в задании, но не любое другое задание. (Результаты бесполезны для меня, если мне не хватает части головоломки, поэтому продолжение работы над этим будет просто пустой тратой процессорного времени.)
Вопрос в том, как лучше всего осуществить остановку.
Одна идея будет:
- Создать один
Dispatcher
экземпляр и сохранить его в течение всего срока службы приложения. - Создать новый
DispatcherQueue
за каждую "работу" (группу задач). ДобавитьCausality
сразу после созданияDispatcherQueue
, - В обработчике очереди исключений вызовите
Suspend()
наDispatcherQueue
, - Перед удалением очереди диспетчера удалите причинно-следственную связь.
Интересно, можно ли считать это предложение лучшей практикой или есть лучший подход для решения такого, вероятно, довольно распространенного сценария.