WPF整理-处理没有注意到的异常
在.NET中,我们使用try-catch-finally来处理异常。但,当一个Exception抛出,抛出Exception的代码又没有被try包围时,程序就崩溃了。
这些异常往往是你没有注意到的。在WPF中,提供了一种处理这些个异常的方式。
举例来说明。
1.先抛出个异常,不用try包围它。
在MainWindow上添加一个如下的Button。
<Window x:Class="HandlingAnUnhandledException.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <StackPanel> <Button Click="OnClick"> <Button.Template> <ControlTemplate> <Grid> <Ellipse Height="100" Width="250" Fill="Pink"/> <TextBlock Text="Button to Throw Exception by DebugLZQ" VerticalAlignment="Center" HorizontalAlignment="Center"/> </Grid> </ControlTemplate> </Button.Template> </Button> </StackPanel> </Window>
在Button的Click事件中抛出个异常
private void OnClick(object sender, RoutedEventArgs e) { throw new InvalidOperationException("Something has gone wrong."); }
如果,我们Ctrl+F5运行这个程序,点击按钮,程序就崩溃了。
WPF如何解决这个问题呢?
2.WPF处理这种异常的方法
在App.xaml.cs中订阅DispatcherUnhandledException事件,并添加相应的事件处理。
App.xaml.cs如下:
public partial class App : Application { public App() { DispatcherUnhandledException += App_DispatcherUnhandledException; } void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) { MessageBox.Show("Error encountered! Please contact support."+ Environment.NewLine + e.Exception.Message); //Shutdown(1); e.Handled = true; } }
这时,当我们Ctrl+F5运行程序。
这样,异常就被捕获并处理了,程序没有崩溃。
Update:刚百度了一下:WinForm也有类似的机制,请参考Kevin Gao的这篇博文:C# winform 捕获全局异常.
Update:
所有 WPF 应用程序启动时都会加载两个重要的线程:一个用于呈现用户界面,另一个用于管理用户界面。呈现线程是一个在后台运行的隐藏线程,因此我们通常面对的唯一线程就是 UI 线程。
这种方法只能捕捉UI线程的异常,及使用了Dispatcher进行线程关联了的线程(其实Dispatcher.Invoke/BeginInvoke就是将要执行的代码,扔到UI线程去执行)的异常。不能捕捉普通的子线程异常。
如:
private void OnClick(object sender, RoutedEventArgs e) { Dispatcher.BeginInvoke(new Action(() => { throw new InvalidOperationException("Something has gone wrong."); })); }
也可以正常捕获。
而:
private void OnClick(object sender, RoutedEventArgs e) { Thread t = new Thread(() => { throw new InvalidOperationException("Something has gone wrong."); }); t.IsBackground = true; t.Start(); }
则不能捕获。
感谢veboys博友的指点~
------------------------------------------
同样的,即使我们用一个try-catch包围如下的异常,异常也不会被Handle:
try { var thread = new Thread(() => {throw new Exception(); }); thread.Start(); } catch (Exception) { MessageBox.Show("Will not execute!"); throw; }
try { Task.Run(() =>{throw new Exception(); }); } catch (Exception) { MessageBox.Show("Will not execute!"); }
--------------
对应Async await 异常:
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e) { try { await Task.Run(() => { throw new Exception(); }); } catch (Exception) { MessageBox.Show("Will execute!"); } }
处理Unhandled exception异常 如下:TaskScheduler.UnobservedTaskException
public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { RegisterEvents(); base.OnStartup(e); } private void RegisterEvents() { TaskScheduler.UnobservedTaskException += (sender, args) => { MessageBox.Show(args.Exception.Message); args.SetObserved(); }; AppDomain.CurrentDomain.UnhandledException += (sender, args) => MessageBox.Show("Unhandled exception."); } }
Update:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
2012-07-08 Android开发?用C#!!
2012-07-08 浅述NUnit单元测试-----以为BubbleSort编写单元测试为例