高效日志查看器设计指南

在开发应用程序时,日志记录是一个重要的环节,它帮助开发者追踪程序的执行过程,同时也为用户诊断问题提供了依据。然而,当应用程序执行长时间运行的任务时,如何有效地将日志信息展示给用户,是一个值得思考的问题。本文将介绍一种高效的日志查看器设计方法,旨在提高应用程序的用户体验和性能。

用户界面的挑战

当应用程序执行一个需要花费数分钟的任务,并执行成千上万的步骤时,如果用户界面(GUI)在此期间没有变化,用户可能会认为应用程序已经冻结。另一方面,用户可能不需要看到所有的步骤,只需要看到几个主要步骤和当前步骤。最简单的方法是只显示主要步骤,但这样用户就无法知道哪个详细的步骤花费了太多时间。但如果用户看到当前步骤显示了几秒钟,他们就知道出了问题。

日志查看器的设计

设计日志查看器时,需要考虑以下几个方面:

  1. 多线程安全地接受日志消息,但不在WPF线程上执行。
  2. 区分临时消息和永久消息。临时消息会被任何后续消息覆盖,而永久消息在后台任务完成后仍然显示给用户。
  3. 在0.1秒内收集所有接收到的消息,并将它们一起传输到WPF线程。WPF线程不能每秒更新GUI数百次,用户也无法读取信息。
  4. 将消息转换为WPF FlowDocument元素。控制字体、大小、边距等可能相当复杂,后台任务的编写者不需要知道WPF。为了指定所需的格式,他只需与消息一起传递一个StringStyleEnum值,该值在StyledString.cs中为该应用程序特别定义。

多线程实现

在实现多线程时,考虑使用一些复杂的多线程安全集合来存储消息,但最终决定只使用简单的列表,并锁定后台任务的每个Write()和WPF线程的每个Read()。如后所述,Read()非常快,每秒只执行10次,这意味着几乎不会有任何同时锁定。

支持格式化文本

后台任务通常属于业务层代码,不应该依赖于WPF。因此,LogViewer定义了自己的StringStyleEnum: public enum StringStyleEnum { none = 0, normal, label, header1, errorHeader, errorText, stats } 这些值可以根据应用程序的需要有所不同。文件StyledString.cs还包含静态方法StyledString.ToInline(),它将消息及其StringStyleEnum值转换为WPF flowdocument Run。

在应用程序中使用LogViewer

可以从GitHub获取LogViewer的最新版本: 把它放在自己的DLL LogViewerLib中。与其将该库链接到应用程序中,建议只复制两个文件,LogViewer.cs和StyledString.cs。需要根据应用程序的需要更改StyledString.cs的内容,因此,如果不与GitHub上的LogViewer同步代码,可能会更好。

测试LogViewer

LogViewerTestApp是用来测试LogViewer的WPF应用程序。运行LogViewerTestApp可以让了解LogViewer的行为。

  1. Test1写入一些不同格式的文本。注意最后一行"tempLine3"是一个临时行。只要再次按下TestX按钮,该行就会被覆盖。
  2. Test2尽可能快地写入临时行。令人惊讶的是,LogViewer可以每秒处理一百万条临时消息!毕竟,它只是在RAM中收集它们,但每0.1秒只发送1条给WPF。
  3. Test3不断写入新行。这有助于测试用户是否可以停止和继续自动滚动。如果用户想要检查一个永久行,他可以滚动到它,这会停止自动滚动。一旦他想再次激活自动滚动,他只需滚动到底部。

进一步阅读

如果读到这里,可能真的对WPF感兴趣,在这种情况下,会热情推荐一些其他WPF文章。这篇文章觉得读起来没那么有趣,但一些文章真的很有帮助,给提供了在其他地方找不到的WPF见解:

  • 深入WPF布局和渲染
  • WPF开发者必读:WPF控件测试台
  • WPF颜色、颜色空间、颜色选择器和为普通人创建自己的颜色的终极指南
  • 使用绑定格式化WPF DataGrid指南
  • WPF DataGrid:解决排序、ScrollIntoView、刷新和焦点问题
  • 避免WPF DataGrid限制,用几行代码替换它
  • WPF LinearGradientBrush参数解密
  • WPFScrollBar高级指南或如何显示数百万种颜色组合
  • 提高WPF DispatcherTimer精度

GitHub项目

还写了几个开源项目在GitHub上:

  • StorageLib:对于单用户WPF应用程序的数据库的惊人替代品。程序员只需要定义他想要使用的C#类,代码生成器就会编写所有用于在本地磁盘上永久创建、更新和删除数据的代码。这大大加快了开发者的工作,因为他不再需要使用任何SQL、Entity Framework等。查询是在Linq中完成的,运行速度超快。代码执行速度比任何数据库都快。支持事务、备份等。在几个项目中已经无错误运行了5年以上。
  • TracerLib:有效地实时收集多线程数据,可以存储在文件中,也可以只存储在RAM中,过一段时间后丢弃。这对于异常处理很有用,因为这可以告诉用户在异常发生之前发生了什么。
  • WpfWindowsLib:WPF控件用于数据输入,检测是否缺少所需数据或数据是否已更改。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485