WPF 窗体关闭的方式
1.Close();关闭当前窗口 在WPF应用程序的关闭是有ShutdownMode属性设置,具有3中枚举类型的值: 1)OnLastWindowClose(默认值)---应用程序最后一个窗体关闭时关闭应用程序
2)OnMainWindowClose---应用程序主窗体关闭时关闭应用程序 3)OnxplicitShutdown---显示调用关闭 这种情况是指当 shutdownMode 值为 0nMainwindowclose 时关闭主窗体,如果有多余线程此方式不适用
2.Application.Current.Shutdown0 只关掉了UI而后台进程没有关掉,直到所有的后台线程结束才算真的结束。 3.Environment.Exit(0) 强制退出,即使有其他的线程没有结束。,不过它不会执行代码块的finally块(如果有的话),但资源清理还是要进行的。它是最常见的退出当前进程的方法之一 4.Process对象实例.Kill() var currentProcess =Process.GetCurrentProcess();
currentProcess.Ki11(); 从名字也可以看出来,直接杀掉,不给喘息喘息机会,Ki方法会直接结束整个进程,不进行常规资源清理(什么finally块等.) 5.Environment类的FailFast:这是最暴力最彻底最直接的方法,它甚至不需要向操作系统返回进程退出代码(ExitCode),
直接结束当前进程并在应用程序事件薄中写入信息,用于程序出现致命错误需要立即停止,一般不建议使用。
<Application x:Class="WpfApp1.ApPxmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local= "clr-namespace:WpfApp"
ShutdownMode="OnMainWindowClose"
StartupUri-"MainWindow.xaml"> </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();
}