WPF应用程序在呈现文本时冻结(wpfgfx问题)

TL; DR:

  • 应用程序是使用WPF构build的,运行在.Net 3.5上
  • 应用程序的最新版本和旧版本可以在许多不同的机器上正常工作
  • 在一个特定的机器上,它以一种奇怪的方式发生故障:
    • 或者不启动,显示黑屏而不是“欢迎”屏幕; 在黑屏上无法做任何事情
    • 或者确实启动并正常工作,直到文本框出现,直到用户开始input文本为止。 那么应用程序立即挂起

背景:

我在.Net 3.5上构build了一个WPF应用程序。 我已经检查了不同操作系统,从Windows XP到Windows 7的各种机器上的应用程序 – 它运行良好,没有错误等。它也适用于我的客户端的几个目标机器,再次包括XP和W7。

然而,在一台机器上,它突然停止工作。 我的客户把机器寄给了我,以便我可以调查。 从驱动器上的文件中,我可以看到有更旧的版本,它们被客户使用了几个月。 我也看到最新的版本尚未安装在这台机器上。 所以,我试着先运行旧版本,看看有什么问题。

用户看到的是:

  • 应用程序的最旧版本(比如v1,v2)根本不起作用。 当它们启动时,应用程序显示的唯一东西是… 完全黑色的窗口 。 应该有一个“欢迎”屏幕,由几个图像和标签和一个button组成。 该应用程序不冻结,它是“响应”(Win7可以与它沟通,窗口变暗)。
  • 最后(但不是最新的,让我们命名为v3)应用程序运行良好,一切都可以点击,function工作正常,除了一个。 当用户被要求提供密码时,用户在popup窗口中显示单个TextBox 。 当用户在该文本框中input至less一个字符时,应用程序将冻结。 它甚至在渲染了被掩盖的密码“*” 之前就冻结了。 冻结是完全的,应用程序停止响应(窗口变暗 ,操作系统要closures它),CPU达到100%(实际上是50%,双核系统),唯一的停止方法是通过任务pipe理器。
  • 然后我安装并尝试运行最新版本(v4) – 它的行为就像上面的v3

  • 我也尝试重新安装所有的版本,只是为了确保.EXE / .DLL文件没有损坏 – 没有任何变化(v1 / 2 – 黑色,v3 / 4 – 冻结文本)

技术比特,只是供参考:

  • 该应用程序非常简单,一个可执行文件没有共享库和共享configuration。 最新版本只能与旧版本交互。 说真的,我故意以一种可以“复制”的方式创build应用程序,并且可以将多个实例安全地保存在单独的文件夹中。
  • 所有版本的应用程序(v4,v3,v2,v1)都可以在所有其他机器上正常运行,并具有各种版本的Windows
  • 该问题不能与用户文件或configuration相关,我试图将它们从有问题的机器复制到健康的机器,并且问题不重复

  • 与密码框相关:代码中绝对没有可能产生死锁或冻结的事件处理程序。 密码文本框没有文本更改的处理程序。 我的代码只有在“确定”button被按下后才能读取文本。 当用户input第一个字符时,应用立即冻结,用户甚至没有机会按“OK”

  • 与启动相关:应用程序在启动时几乎不做任何事情。 它只是显示某种forms的飞溅/欢迎屏幕。 除了一个漂亮的用户界面和一个button,没有任何逻辑。 用户没有按下该button的机会。 当应用程序启动时,屏幕是黑色的,没有内容,甚至没有飞溅/欢迎图像。

追踪和观察:

我专注于TextBox部分,因为它更加细化。
我有应用程序再次冻结,并与ProcessHacker检查线程。
除了典型的线程之外,其中一个线程正在坐着,

  wpfgfx_v0300.dll MilGlyphRun SetGeometryAtRenderTime wpfgfx_v0300.dll MilGlyphRun SetGeometryAtRenderTime ... wpfgfx_v0300.dll MilContent DetachFromHWND 

这当然是WPF层本身的问题。 从“ DetachFromHWNDDetachFromHWND告诉我什么都没有,但MilGlyphRun肯定是关于文本渲染。 它试图呈现文本时冻结 。 我已经检查了老版本的应用程序的黑屏,但我无法捕捉,因为应用程序没有被冻结,只是黑色。

所以..

  • 我已经从字面上应用了所有未完成的更新(例如,其中150个,大约800 Mb,其中大部分是OS和.Net框架)
  • 我试过重新安装所有的video驱动程序

没有变化,仍然黑屏,仍然冻结。

所以,重点回到这个问题上。 它没有呈现文字。 听起来很明显,因为当用户在一个文本框中input一个字符时,它会死锁,但它不是显而易见的! 用户被提供了吨吨不同的TextBoxes直到他终于到了PasswordBox TextBoxes 。 所有TextBoxes工作正常,只有这一个失败。 为什么旧版本的应用程序显示黑屏,新版本显示正确的“欢迎”屏幕? 这些问题怎么可能相关?

连接是: Windows Presentation Foundation字体缓存服务。

资料来源:

WPF使用字体缓存服务,作为一个单独的进程运行,以便缓存字体。 每当您的WPF应用程序需要绘制一些文本,它可能会要求缓存服务的字体。 偶尔,字体缓存可能会被破坏 ,然后它可能会随机影响任何WPF应用程序

不幸的是,重新启动服务是不够的。 发生这种情况时,您必须删除该服务保留在磁盘上的所有FontCache文件。 在删除它们之前,您必须停止"Windows Presentation Foundation Font Cache服务(或者在您的语言中调用的任何内容,例如波兰语的Usługa buforowania czcionek platformy Windows Presentation Foundation中的Usługa buforowania czcionek platformy Windows Presentation Foundation )。然后,转到

  • Win7: %systemdrive%\Windows\ServiceProfiles\LocalService\AppData\Local\
  • Vista: %systemdrive%\Windows\ServiceProfiles\LocalService\AppData\Local\
  • WinXP: %systemdrive%\Documents and Settings\LocalService\Local Settings\Application Data

并删除所有类似FontCache.dat文件。 源文章只提到一个文件(FontCache3.0.0.0.dat,但在我的情况下,大约有8个文件具有相似的命名约定)。

在删除它们并重新启动服务之后,我的应用程序的所有版本都再次正常运行。 没有黑色的屏幕,没有冻结的文本框。