【问题标题】:Handling exception from non-awaited Task [duplicate]处理来自非等待任务的异常[重复]
【发布时间】:2018-01-15 02:43:03
【问题描述】:

假设我有一个带有 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
}

所以,我只是运行 MyAwesomeMethod(即发即弃),并想做一些其他工作,但我也想知道是否有任何未处理的异常。但是应用程序成功完成,没有任何问题的迹象(异常被吞没了)。

如何处理来自 MyAwesomeMethod() 的异常,而不等待它或使用 Task.Run(...).Wait()?

【问题讨论】:

  • but I also want to know if there any unhandled exceptions. -- 那不是真正的一劳永逸吧?
  • 没有理由在线程池线程中启动另一个异步操作。如果您想启动MyAswsomeMethod,请致电MyAwesomeMethod。它已经是异步的。将其包装在异步 lambda 中并在线程池线程中启动它都无济于事,只会浪费系统资源。
  • @Servy 其实是有原因的:如果一切正常,我不想知道有关 MyAwesomeMethod 的任何信息,但我确实想知道其中有关未处理异常的所有信息。
  • @Andrew 我提到的两件事对这种行为都没有任何影响。

标签: c# .net exception-handling task-parallel-library unobserved-exception


【解决方案1】:

所以,我只运行 MyAwesomeMethod(即发即弃)...但我也想知道是否有任何未处理的异常。但应用程序成功完成,没有任何问题迹象(异常被吞没了)。

那不是“一劳永逸”。 “一劳永逸”的字面意思是你不在乎任务何时(或是否)完成(或错误)。

如何在不等待或不使用 Task.Run(...).Wait() 的情况下处理来自 MyAwesomeMethod() 的异常?

还是使用await

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

【讨论】:

    【解决方案2】:

    您可以在任务完成后查看status

    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 { }
        }
    });
    

    【讨论】:

    • 好吧,谢谢,很好的尝试:) 如果我找不到任何其他解决方案,我会使用它。
    • 玩转状态并在AwesomeMethod 函数中返回一些东西!
    【解决方案3】:

    例如,您可以将后台任务中的代码包装在 try...catch 块中,并在您进入 catch 块时立即引发事件(如果您这样做的话)。

    喜欢

    event EventHandler<Exception> exceptionInWorker;
    

    在任务中做

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 好吧,他订阅了它,但除此之外什么都不做。处理程序应将 UnobservedTaskExceptionEventArgs 作为其第二个参数,通过它,他可以通过其 Exception 属性访问未处理的异常。并记录有关它的所有信息。
      猜你喜欢
      • 2016-11-07
      • 2014-06-30
      • 1970-01-01
      • 2011-01-15
      • 1970-01-01
      • 2013-09-22
      • 1970-01-01
      • 1970-01-01
      • 2015-11-12
      相关资源
      最近更新 更多