简体   繁体   English

集中异步任务的异常

[英]Centralizing exceptions from asynchronous tasks

I implemented a custom HandleErrorAttribute in my MVC application and it's been working great to somehow centralize and catch ALL the exceptions that occur in the application. 我在MVC应用程序中实现了自定义HandleErrorAttribute ,并且在某种程度上集中并捕获应用程序中发生的所有异常一直非常HandleErrorAttribute

public class CustomHandleErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        ....
    }
}

Problem is: I've started to implement some async tasks, like this one: 问题是:我已经开始实现一些异步任务,例如:

Task.Factory.StartNew(() => DoSomethingAsync());

And realized that my CustomHandleErrorAttribute is not intercepting the exceptions that happen in those methods: in this case, if an exception takes place inside the DomeSomethingAsync() method, then my HandleErrorAttribute won't catch it; 并意识到我的CustomHandleErrorAttribute不会拦截那些方法中发生的异常:在这种情况下,如果DomeSomethingAsync()方法内部发生了异常,则我的HandleErrorAttribute将无法捕获该HandleErrorAttribute and Global.asax wont either. Global.asax不会。

What's a good implementation for centralizing exceptions that occur in asynchronous tasks? 有什么好的方法可以集中化异步任务中发生的异常? I don't want to implement a simple try/catch block in every method: I want to count with some kind of handler that captures them. 我不想在每种方法中实现一个简单的try / catch块:我想用某种捕获它们的处理程序来计数。

A good way is to not use Task.Factory.StartNew , especially not on async methods. 一个好的方法是不要使用Task.Factory.StartNew ,尤其是不要在异步方法上使用。

Simply invoke the async method directly and await the returned task. 只需直接调用async方法并等待返回的任务即可。 Exceptions in that task will be rethrown and handled by the same mechanism as all your other exceptions: 该任务中的异常将通过与其他所有异常相同的机制来重新抛出和处理:

await DoSomethingAsync();

Task.Factory.StartNew is useful for offloading work to aa ThreadPool thread, however you're already on a ThreadPool thread so this isn't needed. Task.Factory.StartNew对于将工作卸载到ThreadPool线程很有用,但是您已经在ThreadPool线程上,因此Task.Factory.StartNew

If you want to abandon that task, you should realize nothing guarantees it would continue running. 如果您要放弃该任务,则应该意识到并不能保证它将继续运行。 The application pool can be recycled while the task is running because nothing waits for it. 任务运行时可以回收应用程序池,因为没有任何等待。

If you want to do "fire and forget" in asp.net you should use something like HangFire (more in Fire and Forget on ASP.NET ) 如果要在asp.net中执行“即发即忘”操作 ,则应使用类似HangFire的方法(有关Fire和ASP.NET上的 “忘记”的更多信息)


In the world outside asp.net you can simply add a handler as a continuation using ContinueWith with TaskContinuationOptions.OnlyOnFaulted to make sure it only runs if there were exceptions, for example with an extension method: 在asp.net之外的世界中,您可以使用ContinueWithTaskContinuationOptions.OnlyOnFaulted来简单地添加一个处理程序作为延续,以确保它仅在有例外的情况下运行,例如使用扩展方法:

public static void HandleExceptions(this Task task)
{
    task.ContinueWith(
        faultedTask => HandleException(faultedTask.Exception),
        TaskContinuationOptions.OnlyOnFaulted);
}

And use it like this: 并像这样使用它:

DoSomethingAsync().HandleExceptions();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM