Unhandled exception handler not called for Metro / WinRT UI async void event handler

大憨熊 提交于 2019-11-28 08:28:07

Answered here: No UnhandledException fired from async event callback

It is a known limitation of WinRT. Hopefully, it gets fixed in the next update.

The solution in the following post worked for me, with one small change: I had to move AsyncSynchronizationContext.Register(); to the App.OnLaunched event

http://www.markermetro.com/2013/01/technical/handling-unhandled-exceptions-with-asyncawait-on-windows-8-and-windows-phone-8/

As explained in the documentation (source: http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.application.unhandledexception.aspx):

It’s important to be aware of several limitations of the Application.UnhandledException event. This event is only used with exceptions encountered by the XAML framework. Exceptions encountered by other Windows Runtime components or parts of the application that are not connected to the XAML framework will not result in this event being raised.

For example, if a different Windows component calls into application code and an exception is thrown and not caught, the UnhandledException event won’t be raised. If the application creates a worker thread, and then raises an exception on the worker thread, the UnhandledException event won’t be raised.

As pointed out in this conversation, only way to retrieve exceptions happening in a worker thread is to wrap them in a try/catch block. As a consequence, here's the workaround I'm using in my app: instead of using Task.Run or equivalents to execute code on a worker thread from the UI, I'm using this method:

/// <summary>
/// Runs code in a worker thread and retrieves a related exception if any.
/// </summary>
/// <param name="target">The target.</param>
/// <param name="action">The action.</param>
public static void SafeRun(this DependencyObject target, Action action)
{
    Task task = ThreadPool.RunAsync(o =>
    {
        try
        {
            action();
        }
        catch (Exception ex)
        {
            /* Call the same error logging logic as in the UnhandledException event handler here. */
        }
    }).AsTask();
    task.Wait();
}

Bottom line is that to log all errors in your app, you should:

  1. Subscribre to the UnhandledException event to get XAML stack related errors,
  2. Wrap actions happening in a worker threads in a try/catch block.

From my point of view the only right answere was downvoted here (Try UnobservedTaskException event of TaskScheduler)

the problem is that you are using 'async void' where the exceptions cannot be handled. This is not a WinRT limitation but as design behaviour of async. You need to understand the async deeply to correctly implement exception handling here. See this article: http://msdn.microsoft.com/en-us/magazine/jj991977.aspx

Exceptions are rethrown whe GC collects the tasks as unobserved. You can get them by registering TaskScheduler UnobservedTaskException event. Note - it takes some time till the exception arrives there, because it is noted with garbage collector.

Generally do not use 'async void', but in UI event handlers you have to, so this is thy only way..

Try UnobservedTaskException event of TaskScheduler

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!