Как перехватить и обработать необработанные исключения, которые происходят внутри Task.Factory - PullRequest
0 голосов
/ 10 февраля 2020

Я закодировал это внутри запуска приложения

внутри App.xaml.cs

public App()
{
    AppDomain currentDomain = AppDomain.CurrentDomain;

    currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);

    DispatcherUnhandledException += App_DispatcherUnhandledException;

    Application.Current.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(Application_DispatcherUnhandledException);

    TaskScheduler.UnobservedTaskException += new EventHandler<UnobservedTaskExceptionEventArgs>(Application_DispatcherUnhandledException2);

    this.Dispatcher.UnhandledException += Dispatcher_UnhandledException;


}

private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
    writeMessage(e.Exception);
}

private void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
    writeMessage(e.Exception);
}

private static void writeMessage(Exception e)
{
    string srMsg = e.InnerException?.Message;

    if (srMsg != null)
    {
        srMsg += "\r\n\r\nStack\r\n" + e.InnerException?.StackTrace;
    }

    if (srMsg == null)
    {
        srMsg = e.Message + "\r\n\r\nStack\r\n" + e.StackTrace;
    }

    srMsg += "\r\n\r\n*********\r\n\r\n";

    File.AppendAllText("global_errors.txt", srMsg);

}

private static void Application_DispatcherUnhandledException2(object o, UnobservedTaskExceptionEventArgs e)
{
    writeMessage(e.Exception);
}

private static void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
    writeMessage(e.Exception);
}

private static void MyHandler(object sender, UnhandledExceptionEventArgs args)
{
    Exception e = (Exception)args.ExceptionObject;
    writeMessage(e);
}

Однако, это все еще не захватывает заводские ошибки задач

Например

enter image description here

enter image description here

enter image description here

enter image description here

Ничто из предложенного в этой теме не работает Глобальный обработчик исключений WPF

Ответы [ 2 ]

2 голосов
/ 10 февраля 2020

Исключение выдается, только если вы наблюдаете Task, например, вызывая Wait() или .Result или обращаясь к его свойству Exception.

Ненаблюдаемые исключения не генерируются, если вы не используете элемент конфигурации <ThrowUnobservedTaskExceptions>, чтобы вернуться к поведению, которое было по умолчанию в. NET Framework 4 и завершает процесс:

<runtime>
  <ThrowUnobservedTaskExceptions enabled="true"/>
</runtime>

Если вы действительно хотите перехватить исключение, вы должны сделать это в делегате, который вы передаете Task.Factory.StartNew. Вы можете обернуть эту функцию в метод расширения, как предложено здесь .

1 голос
/ 10 февраля 2020

Получить StackTrace можно несколькими способами, это зависит от того, что больше всего соответствует вашим потребностям. В любом случае, я бы посоветовал вам попробовать следующее.

  1. Добавьте обратный вызов к событию AppDomain.FirstChanceException, в начале вашего проекта, например, до возникновения ошибок, которые вы хотите поймать / войти. Это может выглядеть примерно так:
public static Main()
{
    AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;
}

private static void CurrentDomain_FirstChanceException(object sender, FirstChanceExceptionEventArgs e)
{

}
После этого добавьте Environment.StackTrace в методе CurrentDomain_FirstChanceException. Он будет содержать текущий StackTrace как string. Из моего тестирования это включает FileName и FileLineNumber.
var currentStackTrace = Environment.StackTrace;

// Now it is on to you on what you want to do with the StackTrace. This could be some kind of logging.

Обратите внимание, что это будет регистрировать ALL исключений, выданных AppDomain, нет независимо от того, обрабатываются ли они кодом, например, try/catch.

...