Having a complex sequence of tasks, implementing error handling can quickly bloat the code when using try/catch blocks and stuff like Choice receivers on PortSet<ActualResult, Exception>
for every little task.
Thankfully the CCR seems to offer a mechanism to handle exceptions in a more general way for a graph of tasks: causalities. A typical example looks like this:
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
In my case, I have a computing intensive application using the CCR to implement a scatter/gather scenario, splitting "jobs" into a bunch of parallelized tasks. (Besides that, more then one of these jobs can run at the same time.) In case that one task fails, I want to to stop all the remaining tasks in the job, but not any other job. (The results are of no use to me if I'm missing a piece of the puzzle, so continuing to work on this would be just a waste of CPU time.)
The question is what the best way would be to implement the stopping.
One idea would be:
- Create one single
Dispatcher
instance and keep it over application lifetime. - Create a new
DispatcherQueue
for every "job" (a group of tasks). Add theCausality
immediately after creating theDispatcherQueue
. - In the handler for the exception queue, call
Suspend()
on theDispatcherQueue
. - Before disposing the dispatcher queue, remove the causality.
I wonder if this suggestion can be regarded best practice, or if there is a better approach to deal with such a - probably fairly common - scenario.