CCR:使用因果关系处理错误的最佳实践
对于复杂的任务序列,在对每个小任务使用 try/catch 块和 PortSet
上的 Choice 接收器等内容时,实现错误处理会很快使代码变得臃肿。
值得庆幸的是,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 来实现分散/聚集场景,将“作业”拆分为一堆并行任务。 (除此之外,这些作业中的多个可以同时运行。)如果一项任务失败,我想停止该作业中的所有剩余任务,但不停止任何其他作业。 (如果我遗漏了一块拼图,结果对我来说毫无用处,因此继续解决这个问题只会浪费 CPU 时间。)
问题是实现停止的最佳方法是什么。
一种想法是:
- 创建一个
Dispatcher
实例并在应用程序生命周期内保留它。 - 为每个“作业”(一组任务)创建一个新的 DispatcherQueue。 创建
DispatcherQueue
后立即添加Causality
。 - 在异常队列的处理程序中,对
DispatcherQueue
调用Suspend()
。 - 在处理调度程序队列之前,请删除因果关系。
我想知道这个建议是否可以被视为最佳实践,或者是否有更好的方法来处理这种可能相当常见的情况。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
对我来说这似乎是一个很好的方法。
Seems like a good way to way to go about it to me.