在 UWP 应用程序中处理 Dispatcher 异常
Handling Dispatcher exceptions in UWP app
在我的 UWP 应用程序中,我需要从另一个线程更新 UI,我正在使用 CoreDispatcher 来执行此操作。我希望任何未处理的异常都会终止应用程序,就像 UI 线程中的异常一样,但情况似乎并非如此。下面的 RunAsync lambda 中抛出的异常被 UWP 静默忽略。此外,这些异常永远不会发送到任何应用程序 UnhandledException 处理程序(下面示例中的第二个异常是)。
这是怎么回事? Dispatcher 是否只是捕获所有异常并默默地忽略它们?
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");
}
}
要处理来自其他线程的错误,只需使用 ContinueWith
函数。您的代码可以是这样的:
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);
});
它们在技术上并不是无人处理的,因为任务中的异常是 "caught" 并包装在 Task 对象中。如果该异常未以某种方式从任务中消耗(通过等待任务或使用 .ContinueWith),当任务被垃圾收集时,您可以收听 TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
以获取该异常 - 您可以手动终止应用程序如果您愿意,可以从那里开始。
当然要记住,根据您编写代码的方式,不能保证 Task 会很快被垃圾收集,或者根本不会被垃圾收集 - 所以如果您在任何地方存储对 Tasks 的引用如果您不小心,很可能会默默地吞下此类异常。
在我的 UWP 应用程序中,我需要从另一个线程更新 UI,我正在使用 CoreDispatcher 来执行此操作。我希望任何未处理的异常都会终止应用程序,就像 UI 线程中的异常一样,但情况似乎并非如此。下面的 RunAsync lambda 中抛出的异常被 UWP 静默忽略。此外,这些异常永远不会发送到任何应用程序 UnhandledException 处理程序(下面示例中的第二个异常是)。
这是怎么回事? Dispatcher 是否只是捕获所有异常并默默地忽略它们?
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");
}
}
要处理来自其他线程的错误,只需使用 ContinueWith
函数。您的代码可以是这样的:
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);
});
它们在技术上并不是无人处理的,因为任务中的异常是 "caught" 并包装在 Task 对象中。如果该异常未以某种方式从任务中消耗(通过等待任务或使用 .ContinueWith),当任务被垃圾收集时,您可以收听 TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
以获取该异常 - 您可以手动终止应用程序如果您愿意,可以从那里开始。
当然要记住,根据您编写代码的方式,不能保证 Task 会很快被垃圾收集,或者根本不会被垃圾收集 - 所以如果您在任何地方存储对 Tasks 的引用如果您不小心,很可能会默默地吞下此类异常。