【问题标题】:Saving .NET user settings takes very long time保存 .NET 用户设置需要很长时间
【发布时间】:2015-01-15 18:07:02
【问题描述】:

在我们的 .NET 4.0 Winforms 应用程序中,一些用户(所有 Win7 x64)最近在应用程序使用此代码保存其设置时经历了非常长的等待时间(与其他用户相比):

Properties.Settings.Default.Save();
  • 典型持续时间:0.5 到 1 秒
  • 极端持续时间:15 到 20 秒

应用程序设置(范围:用户,保存在 AppData\Local\\ 下的 user.config 中的所有内容)由几个自定义类以及两个表示打印机设置的类组成: System.Drawing.Printing.PageSettings 和 System.Drawing.Printing.PrinterSettings

在其中一台机器上使用 GlowCode 分析器,我发现以下函数需要 17 秒:

<Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterPrinterSettings_x003A__x003A_Write9_PrinterSettings Nodes="1" Visits="1" percent_in_Child="100.00 %" Time_in_Child="17.456" Time="17.456" Avg._Time_in_Child_="17.456" Avg._Time="17.456" Blocks_net="12" Bytes_net="1024" Blocks_gross="1087" Bytes_gross="494146" />

其中持续时间几乎均分到三个 getter(取自 GlowCode 查看器):

  • PrinterSettings::get_PaperSizes
  • PrinterSettings::get_PaperSources
  • PrinterSettings::get_PrinterResolutions

做一些研究发现以下页面: https://social.msdn.microsoft.com/Forums/vstudio/en-US/8fd2132a-63e8-498e-ab27-d95cdb45ba87/printersettings-are-very-slowhttp://www.pcreview.co.uk/forums/papersources-and-papersizes-really-slow-some-systems-t3660593.html,引用:

在某些系统上,尤其是 Vista x64 系统上,它需要很长时间(5 到 15 如果为 x64 编译,则为秒,如果为 x86 编译,则为 10-20 秒)枚举 printersettings 对象的 papersources 或 papersized 集合。

使用仅保存 PrinterSettings 的小型测试应用程序显示其中一台“慢”机器上的节省时间约为 3.5 秒,而另一台则对 0.2 秒的持续时间印象不深,这与我的快速开发机器相对应。

关于原因以及如何改进此问题的任何想法?

我怎样才能找到这些延误的真正原因?

编辑:感谢您指出打印机设置是通过驱动程序获取的,这可能解释了某些机器上的延迟。

在我以后无法访问的机器上更新打印机驱动程序是不可能的。

另外,我不会(我知道我知道)减少要保存的 PrinterSettings 信息,因为有些人最终可能会遇到延迟并破坏向后兼容性......

也许如果我在后台尝试序列化(在用户完成一些打印机更改之后?)它可能会加快速度......

【问题讨论】:

  • 我怀疑 PrinterSettings 对象必须重新查询打印机以获取它的信息,这很慢。为什么必须存储 PrinterSettings 对象?如果物理打印机发生变化,从中获得的数据可能会发生变化。最好不要缓存这些信息。
  • 首先,欢迎来到 Stack Overflow!其次,为第一个写得很好的问题+1!您显然已经对此进行了大量研究记录了它。
  • 我有一个项目在很大程度上做同样的事情,而且没有问题。现在在开车上班的车上,我可以把它挖出来今天早上晚些时候发布。虽然是vb。如果我没记错的话,它涉及使用以不同方式序列化每个位的自定义包装器
  • @bettwäsh 我有一个答案,但它在 VB.net 中并且很长(很多代码)。我没有时间通过​​转换器运行它并测试它是否有效,但如果你喜欢它,我可以发布所有类(在 VB 中)/包装器/序列化器。总体而言,这更像是一个 .NET 问题,而不是仅 C# 的问题

标签: c# .net winforms app-config


【解决方案1】:

第一个建议:

检索纸张来源和纸张尺寸的调用正在传递给驱动程序。最好的办法是确保安装了最新版本的驱动程序。驱动程序的旧版本(特别是包装盒中 CD 中的驱动程序)可能是旧版本且存在故障。如果您还没有,请访问制造商的网站,获取最新的。

第二个建议

除此之外,这会很痛苦,但您可以尝试使用底层的 Win32 API 而不是 CLR 对应的 API。在这种情况下,您将调用GetPrinter,请求PRINTER_INFO_2 结构。一旦你有了它,你可以检查 pDevMode 以获得一个 DEVMODE 结构,其中包含你正在寻找的所有信息。

This questionthis question 应该会有所帮助。

不是保留整个 PrinterSettings 类实例,而是仅保留单个设置作为它们的基本类型。保持简单——字符串、整数、布尔值等。显然,序列化程序正在请求与打印机通信,这就是引入延迟的原因。我敢打赌,如果你抓住个别班级成员并自己对他们进行序列化,你会看到进步。

显然,这意味着当您加载设置时,您需要将所有这些设置反序列化回一个新的 PrinterSettings 类,然后应用它们。

EDIT 1,回应问题编辑

确实如此 - 您可以让 Save() 在后台异步运行。您唯一的问题是,如果用户在保存完成之前尝试结束进程(关闭应用程序)。您必须维护一个关于是否正在发生保存的布尔值(当回调触发时设置为 false)。如果用户尝试退出应用并且 bool 为真,则提出“请稍候,正在保存设置...”直到 bool 变为假。

【讨论】:

  • 重新阅读您的问题后,我现在怀疑我的答案的后半部分是否会有所帮助。听起来您无法控制正在调用以请求打印机设置的代码。我更新驱动程序的建议仍然有效。
  • 用更合适的建议编辑了我的答案。
  • 您可以只使用前台线程 (Thread.IsBackground = false) 并始终显示“关闭时请稍候”消息。这样你就不需要传达线程的状态了。
【解决方案2】:

因此,似乎有些机器需要很长时间才能通过已安装的驱动程序查询页面和打印机设置。我找不到更多细节。

为缩短关机时间,在用户更改打印机设置后,上述部分设置分配并保存在后台线程中。这大约需要 10 秒。

在关机(表单关闭)期间,这些设置不会再次分配,但我们仍然保存所有设置(使用 Properties.Settings.Default.Save())并且序列化程序以某种方式识别它们没有对查询进行了更改,因此保存非常快:

在 0.02 到 0.05 秒之间,但仍然正确保存所有设置!

有趣的事实:这个问题是在我们购买新办公室打印机的那一周首次报告的 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-07
    相关资源
    最近更新 更多