简体   繁体   English

处理未等待任务的异常

[英]Handling exception from non-awaited Task

Let's assume I have a console application with Main method, something like this: 假设我有一个带有Main方法的控制台应用程序,如下所示:

public static void Main(string[] args)
{
    AppDomain.CurrentDomain.UnhandledException += (sender, eventArgs) =>
    {
        Console.WriteLine("App Unobserved");
    };
    TaskScheduler.UnobservedTaskException += (sender, eventArgs) =>
    {
        Console.WriteLine("Task Unobserved");
    };
    Task.Run(async () => await MyAwesomeMethod());
    // other awesome code...
    Console.ReadLine();
}

public static async Task MyAwesomeMethod()
{
    // some useful work
    if (something_went_wrong)
        throw new Exception();
    // other some useful work
}

So, I just run MyAwesomeMethod (fire-and-forget), and want to do some other job, but I also want to know if there any unhandled exceptions. 因此,我只运行MyAwesomeMethod(即弃即用),并想做其他工作,但是我也想知道是否有任何未处理的异常。 But application finishes successfully without any sign of problem (exception is just swallowed). 但是应用程序成功完成,没有任何问题的迹象(只是吞下了异常)。

How can I handle exception from MyAwesomeMethod(), without awaiting it or using Task.Run(...).Wait()? 如何处理MyAwesomeMethod()中的异常,而不等待它或使用Task.Run(...)。Wait()?

So, I just run MyAwesomeMethod (fire-and-forget)... but I also want to know if there any unhandled exceptions. 因此,我只运行MyAwesomeMethod(即发即弃)...但我也想知道是否存在任何未处理的异常。 But application finishes successfully without any sign of problem (exception is just swallowed). 但是应用程序成功完成,没有任何问题的迹象(只是吞下了异常)。

That's not "fire and forget", then. 那不是“生与死”。 "Fire and forget" literally means that you don't care when (or whether) the task completes (or errors). 从字面上看,“开火即忘”意味着您不在乎任务何时(或是否完成)(或错误)。

How can I handle exception from MyAwesomeMethod(), without awaiting it or using Task.Run(...).Wait()? 如何处理MyAwesomeMethod()中的异常,而不等待它或使用Task.Run(...)。Wait()?

Use await anyway: 无论如何都使用await

Task.Run(async () => {
  try {
    await MyAwesomeMethod();
  } catch (Exception ex) {
    Console.WriteLine(ex);
  }
});

You can check the status of your task once it's done. 完成任务后,您可以检查其状态

Task.Run(() => MyAwesomeMethod()).ContinueWith((task) =>
{
    if (task.Status == TaskStatus.RanToCompletion && task.Result != null)
    {

    }
    else
    {
        try
        {
            Logger.LogError(task.Exception.ToString());
            Logger.LogMessage("something_went_wrong");
        }
        catch { }
    }
});

You could for example wrap the code in the background task in a try...catch block and raise an event as soon as you enter the catch block (if you do). 例如,您可以在try ... catch块中将代码包装在后台任务中,并在进入catch块后立即引发事件(如果这样做)。

Like 喜欢

event EventHandler<Exception> exceptionInWorker;

and in the task do 并在任务中做

try
{
    //do something
}
catch (Exception e)
{
    exceptionInWorker?.Invoke(this, e);
}

您可以像执行操作一样订阅TaskScheduler.UnobservedTaskException事件,但是使用将UnobservedTaskExceptionEventArgs作为其第二个参数的处理程序,通过该处理程序,您可以通过其Exception属性访问未处理的异常并记录有关该异常的所有信息。

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

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