使用log4net
注意
稍大点的应用推荐这种方式。可定义参数多。
安装
Nuget
安装log4net
项目根目录添加log4net.config
设置属性
下面两种任选一种即可。
下面两种方式主要是封装的要解决无法在日志中显示异常位置的问题。
默认(推荐)
log4net.config
1 |
|
其中
%class
显示包名和类名
%class{1}
只显示类名
工具类
1 | using System; |
调用
1 | ZLogHelper.Loginfo.Info("课堂启动"); |
如果在应用结束前要上传日志文件,我们就要停止日志,防止文件占用
1 | ZLogHelper.StopLog(); |
打印示例
日志时间:2023-11-06 15:21:41,108 [1]
日志级别:INFO
日志类:SchoolClient.MyApp:35
课堂启动
注意
这里之所以没有把打印日志封装是因为:打印的类和行号是被调用的类,如果封装后,显示的都会是封装的类,那么打印类名和行号就没有意义了。
简单封装(不推荐)
配置如下:
1 |
|
添加工具类
1 | using System; |
注意
在调用记录日志前,要调用
InitLog4Net
方法。因为封装了,所以自带的打印类和行数就不生效了,我们可以自己进行格式化拼接。
调用
1 | ZLogHelper.WriteInfoLog("课堂启动"); |
打印示例
这种方式获取到的文件的路径,暂时没找到获取包名+类名的方式。
日志时间:2023-11-06 14:59:36,168 [1]
日志级别:INFO
日志类:D:\Project\csharp\xh-schoolclient\MyApp.xaml.cs:35
课堂启动
自定义日志类
注意
小应用可以使用这种方式。
工具类
1 | using System; |
调用时
1 | //记录日志 |
异常测试
1 | LogHelper.LogWrite(new Exception("主页面启动")); |
全局异常捕获
这里的示例采用的第三方库的方式。
1 | /// <summary> |
在处理 TaskScheduler.UnobservedTaskException
事件时,确保调用 e.SetObserved()
将异常标记为已观察,以便避免默认的行为,即将异常重新抛出。
也就是说要先调用 e.SetObserved()
,之后再写异常处理的逻辑。
应用退出
方式1
1 | Environment.Exit(0); |
Environment.Exit(0)
方法可以在非 UI 线程中调用,用于终止整个应用程序并返回给操作系统。
Environment.Exit(0)
方法立即终止当前进程,不管当前线程是 UI 线程还是其他线程。
它会终止所有线程,关闭所有打开的句柄,释放所有资源,并立即退出应用程序。
这种方式我只在两个地方用
应用退出时
1 | protected override void OnExit(ExitEventArgs e) |
检测程序唯一时
1 | private static void CheckProcess() |
其它的地方都使用Application.Current.Shutdown()
,否则不会触发程序的OnExit
生命周期事件。
方式2
1 | Application.Current.Shutdown(); |
是的,Application.Current.Shutdown()
方法只能在 UI 线程中调用,否则会抛出 InvalidOperationException
异常。
在 WPF 应用程序中,Application.Current
是一个静态属性,它代表了当前应用程序的 Application
实例。调用 Shutdown
方法将停止应用程序并关闭窗口,结束应用程序的 UI 线程。
在非 UI 线程(例如后台线程或 Task
中)调用 Application.Current.Shutdown()
方法可能会导致已经启动的 UI 线程被阻塞或退出应用程序,因为它们处于不同的线程上下文。
如果必须在非 UI 线程中关闭应用程序,可以通过将调用封装在 Dispatcher.Invoke
或 Dispatcher.BeginInvoke
方法中来实现在 UI 线程上下文中调用 Application.Current.Shutdown()
方法。
例如:
1 | Application.Current.Dispatcher.Invoke(() => { |
这样可以确保 Shutdown()
方法在正确的线程上下文中调用。
应用退出删除空日志
1 | protected override void OnExit(ExitEventArgs e) |
文件是否占用
1 | [ ] |