Kyberias
Kyberias

Reputation: 1250

Handling Dispatcher exceptions in UWP app

In my UWP app I need to update UI from another thread and I'm using the CoreDispatcher to do that. I expect any unhandled exceptions to terminate the app, as exceptions in the UI thread do, but that doesn't seem to be the case. An exception thrown in RunAsync lambda below is ignored by UWP silently. In addition, these exceptions are never sent to any application UnhandledException handlers (the second exception in the example below is).

What is going on? Does the Dispatcher merely catch all exceptions and silently ignore them?

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();

        var dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;

        Task.Run( async () =>
        {
            await Task.Delay(2000);

            await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                throw new Exception("This exception will not terminate the app.");
            });
        });
    }

    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        throw new NotImplementedException("This will terminate the app");
    }
}

Upvotes: 1

Views: 741

Answers (2)

Johnny Westlake
Johnny Westlake

Reputation: 1460

They aren't technically unhanded as exceptions in a task are "caught" and wrapped in the Task object. If that exception isn't consumed in some way from the task (by awaiting the task or using .ContinueWith), when the Task is garbage collected you can listen to TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException; to get that exception - you can terminate the app manually from there if you wish or rethrow.

Keeping in mind of course that depending on how you've written your code, there's no guarantee the Task will be garbage collected with any haste, or indeed at all - so if you're storing references to Tasks anywhere it's very possible to silently swallow such exceptions if you're not careful.

Upvotes: 5

Mohsen
Mohsen

Reputation: 51

To handle the errors from other threads simply use ContinueWith function. Your code can be like:

   Task.Run(async () =>
    {
        await Task.Delay(2000);
        throw new Exception("This exception will terminate the app.");
    })
    .ContinueWith(async (res) =>
    {
        if (res.IsFaulted)
            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                () => throw res.Exception.InnerException);
    });

Upvotes: 0

Related Questions