使用任务并行库时,如何处理所有未经处理的异常?
-
01-10-2019 - |
解决方案 2
似乎没有内在的方法来处理此问题(在将近2周后没有回答这个问题)。我已经推出了一些自定义代码来解决这个问题。解决方案描述非常漫长,因此我已经在博客中发布了。参考 这个帖子 如果您有兴趣。
更新2010年5月7日: 我找到了一种更好的方法,利用任务延续。我创建一个 class ThreadFactory
这会暴露出可以由顶级处理程序订阅的错误事件,并提供了以适当延续附件启动任务的方法。
代码发布 这里.
更新4/18/2011: 根据Nifle的评论,博客文章的邮政编码。
internal class ThreadFactory
{
public delegate void TaskError(Task task, Exception error);
public static readonly ThreadFactory Instance = new ThreadFactory();
private ThreadFactory() {}
public event TaskError Error;
public void InvokeError(Task task, Exception error)
{
TaskError handler = Error;
if (handler != null) handler(task, error);
}
public void Start(Action action)
{
var task = new Task(action);
Start(task);
}
public void Start(Action action, TaskCreationOptions options)
{
var task = new Task(action, options);
Start(task);
}
private void Start(Task task)
{
task.ContinueWith(t => InvokeError(t, t.Exception.InnerException),
TaskContinuationOptions.OnlyOnFaulted |
TaskContinuationOptions.ExecuteSynchronously);
task.Start();
}
}
其他提示
我认为 taskscheduler.unobservedtaskexception事件 是您想要的:
发生故障时发生 任务 未观察到的异常即将触发异常升级策略,默认情况下将终止该过程。
因此,此事件类似于 DomainUnhandledException
您在问题中提到的,但仅出于任务。
顺便说一句,请注意,未观察到的外观策略(是的,这不是一个未观察到的例外,MS Guys再次发明了新单词...),从.NET 4.0变为.NET 4.5。在.NET 4.0未观察到的异常导致过程终止,但.NET 4.5-不要。这全是因为我们在C#5和VB 11中拥有的新异步物。
我看到了两个选项,可用于集中tpl中的异常处理目的:1。使用未观察到的任务异常事件。 2.将连续性用于错误状态的任务。
使用任务调度程序的未观察到的任务异常事件。
任务调度程序有一个未观察到的taskexception事件,您可以使用操作员 +=订阅。
- 注意1:在处理程序的正文中,您需要在未观察到的taskexceptionEventargs参数上进行呼叫setObserved(),以通知调度程序处理例外。
- 注2:当垃圾收集器收集任务时,将调用处理程序。
- 注3:如果您要等待任务,您仍然将被迫通过尝试/捕获块保护等待。
- 注4:.NET 4.0和4.5中未经处理任务异常的默认策略不同。
摘要:这种方法非常适合火灾和尸体任务,也适用于从集中式异常处理政策中逃脱出来的例外。
使用延续来实现故障状态的任务。
使用TPL,您可以使用Method contunwith()将操作附加到任务上,该方法采用附加操作和延续选项。此操作将在任务终止后,仅在根据选项指定的情况下进行调用。尤其:
t.ContinueWith(c => { /* exception handling code */ },
TaskContinuationOptions.OnlyOnFaulted);
安装延续,并在任务t上进行例外处理代码。此代码仅在任务T因未经治疗的例外而终止的情况下才运行。
- 注意1:在异常处理代码中获取异常值。否则它将被冒出来。
- 注2:任务终止后将立即调用异常处理代码。
- 注3:如果异常处理代码的异常将被视为处理,则在等待任务上的尝试/捕获块将无法捕获它。
我认为,对于集中式异常处理,使用从任务继承的自定义任务并通过延续添加了异常处理程序,这将是更好的。并通过使用未观察到的任务异常事件来捕捉尝试使用未自定义任务的尝试。