APP生命周期与全局异常捕获
APP生命周期
程序中关闭APP一般使用一下三种方式
// 关闭窗口,当APP里所有窗口都关闭的时候,App执行退出逻辑,执行Exit事件
this.Close();
// 不管有多少窗口打开,退出当前App,执行Exit事件
Application.Current.Shutdown();
// 杀进程,不执行App的Exit事件
System.Environment.Exit(0);
// 线程-》不关闭的情况下 进程无法释放
<Application x:Class="Zhaoxi.EventLesson.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Zhaoxi.EventLesson"
StartupUri="Window.xaml">
<Application.Resources>
</Application.Resources>
</Application>
第一种,Window窗体运行在Application中,当窗体关闭时Application内无其他任务就直接结束执行
第二种,直接关闭Application
第三种,直接结束程序进程
APP中提供了程序启动与关闭事件
public partial class App : Application
{
public App()
{
// 生命周期事件
this.Startup += App_Startup;
this.Exit += App_Exit;
this.SessionEnding += App_SessionEnding;
}
private void App_SessionEnding(object sender, SessionEndingCancelEventArgs e)
{
//操作系统退出的时候触发
e.Cancel = true;
}
private void App_Exit(object sender, ExitEventArgs e)
{
// 日志记录 数据保存 缓存 数据库
Debug.WriteLine("===========App_Exit");
}
private void App_Startup(object sender, StartupEventArgs e)
{
// 需求 程序运行的时候 exe 传递参数 $ dotnet run -- -- -- -- ---
// 业务:更新 更新程序 不允许双击打开 主程序获取更新列表提交到更新程序
//throw new NotImplementedException();
// 业务场景:应用独立启动 不允许多开,可以在这里检查进程
//MessageBox.Show(string.Join(",", e.Args));
}
}
Startup:程序启动时会触发Startup事件,可以利用该事件在程序启动运行时传参
Exit:程序执行结束时会触发Exit事件,可以做临时参数暂存方便下次运行时恢复;使用System.Environment.Exit(0)方式结束程序不会触发Exit事件
SessionEnding:当程序运行时关闭电脑,会在运行中程序列表中显示该进程
DispatcherUnhandledException——UI线程未被处理的异常捕获
从App对象中订阅DispatcherUnhandledException事件
public partial class App : Application
{
public App()
{
// Dispatcher UI线程 未被处理的异常
this.DispatcherUnhandledException += App_DispatcherUnhandledException;
}
private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message);
}
}
在按钮事件下触发未使用try-catch捕获的异常,会触发DispatcherUnhandledException事件
private void Button_Click(object sender, RoutedEventArgs e)
{
//try
//{
int i = 0;
var result = 100 / i;
//}
//catch (Exception ex)
//{
//}
}
AppDomain.CurrentDomain.UnhandledException——非UI线程未被处理的异常捕获
从AppDomain.CurrentDomain对象中订阅UnhandledException事件
public partial class App : Application
{
public App()
{
// Dispatcher UI线程 未被处理的异常
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// 记录下日志
}
}
在按钮事件下触发Thread线程报错,异常会触发UnhandledException事件
private void Button_Click(object sender, RoutedEventArgs e)
{
var thread = new Thread(new ThreadStart(() =>
{
int i = 0;
var result = 100 / i;
}));
thread.Start();
//thread.IsBackground = true;
}
TaskScheduler.UnobservedTaskException——未被观察到的Task异常捕获
从TaskScheduler对象中订阅UnobservedTaskException事件
public partial class App : Application
{
public App()
{
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
}
private void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
{
}
}
创建两个按钮事件
在按钮1事件下执行Task线程报错,异常会在Task块被GC回收时触发UnobservedTaskException事件
在按钮2事件下执行一次GC回收
private void Button_Click(object sender, RoutedEventArgs e)
{
var t= Task.Run(() =>
{
int i = 0;
var result = 100 / i;
});
}
private void Button_Click1(object sender, RoutedEventArgs e)
{
GC.Collect();
}