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

7

TL;DR:

  • 该应用程序使用WPF构建,运行在.Net 3.5上
  • 新版本和旧版本的应用程序在许多不同的计算机上正常运行
  • 在一台特定的计算机上出现奇怪的故障:
    • 要么无法启动,显示黑屏而不是“欢迎”屏幕;无法在该黑屏上进行任何操作
    • 要么启动并正常工作,直到出现一个文本框并且用户开始输入文本;然后应用程序立即挂起

背景:

我已经使用.Net 3.5构建了一个WPF应用程序。我已经在各种不同操作系统的许多计算机上检查过该应用程序,从Windows XP到Windows 7 - 并且它可以正常运行,没有错误等等。 它也在客户端的几个目标计算机上,包括XP和W7。可是,在一台计算机上,它突然停止了工作。我的客户把这台计算机寄给我以便我调查。从它的驱动器文件中,我可以看到有旧版本的文件,并且它们由客户用了几个月。我还看到最新版本尚未安装在该计算机上。所以,我首先尝试运行旧版本,看看问题在哪里。

用户看到的:

  • 应用程序的旧版本(例如,v1,v2)根本不起作用。当它们启动时,应用程序只显示完全黑色窗口。应该有一个“欢迎”屏幕,由几个图像和标签以及一个按钮组成。该应用程序没有冻结,它是“响应”的(Win7可以与之通信,窗口没有被变暗)。
  • 最后一个版本(但不是最新版本,假设为v3)的应用程序运行良好,一切都可以点击,功能正常,除了一个问题。当要求用户提供密码时,用户将在弹出窗口中呈现单个TextBox。当用户在该文本框中输入至少一个字符时,应用程序会冻结。甚至在渲染密码的掩码'*'之前,应用程序就已经冻结了。冻结是总的,应用程序停止响应(窗口变暗,操作系统希望关闭它),CPU使用率达到100%(实际上是50%,双核系统),唯一停止的方法是通过任务管理器将其终止。
  • 然后,我安装并尝试运行最新版本(v4) - 它的行为与上面的v3相同

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

技术细节,供参考:

  • 这个应用程序非常简单,只有一个可执行文件,没有共享库和共享配置。最新版本与旧版本之间根本没有办法互动。说真的,我故意把这个应用程序设计成可以“复制”并且可以在不同的文件夹中安全地保留多个实例。
  • 所有版本的应用程序(v4、v3、v2、v1)在各种Windows版本的其他计算机上都可以正常工作。
  • 问题与用户文件或配置无关,我尝试将它们从有问题的计算机复制到健康的计算机上,但问题并没有重复出现。

  • 关于密码框:代码中绝对没有任何事件处理程序会导致死锁或冻结。密码文本框没有文本更改处理程序。我的代码仅在按下“确定”按钮后读取文本。当用户输入第一个字符时,应用程序立即冻结,用户甚至没有机会按“确定”按钮。

  • 关于启动:应用程序在启动时几乎什么都不做。它只显示某种形式的闪屏/欢迎画面。除了一个漂亮的界面和一个按钮外,那里没有任何逻辑。用户没有机会按下该按钮。当应用程序启动时,屏幕是黑色的,没有内容,甚至没有闪屏/欢迎画面。

跟踪和观察:

我专注于文本框部分,因为它更细致。
我让应用程序再次冻结,并使用ProcessHacker检查了线程。
除了典型的线程外,有一个线程一直忙于旋转,位于:

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

这显然是WPF层本身的问题。虽然DetachFromHWND并没有告诉我太多,但MilGlyphRun肯定与文本渲染有关。尝试渲染文本时它会卡死。我检查了应用程序旧版本的黑屏问题,但因为应用程序没有冻结,只是变成黑色,所以我无法捕捉到它。
所以......
  • 我已经应用了所有待定更新(大约150个,约800 MB,其中大部分针对操作系统和.Net框架)
  • 我已经尝试重新安装所有视频驱动程序
没有变化,仍然是黑屏,仍然会卡死。
因此,将重点放回到问题上。它无法呈现文本。这听起来很明显,因为当用户在文本框中输入字符时,它会死锁,但这并不明显!用户需要进入大量不同的TextBoxes,直到最终到达PasswordBox。所有TextBoxes都可以正常工作,只有这一个失败了。为什么旧版本的应用程序显示黑屏,而新版本的应用程序可以正确地显示“欢迎”屏幕?这些问题如何相关呢?
1个回答

7
连接是:Windows Presentation Foundation Font Cache 服务。
来源: WPF 使用一个字体缓存服务,作为一个独立的进程运行,用于缓存字体。每当您的 WPF 应用程序需要绘制一些文本时,它可能会向缓存服务请求字体。但是有时字体缓存可能会损坏,然后它将随机影响任何 WPF 应用程序。
不幸的是,仅重新启动服务是不够的。当这种情况发生时,您必须删除此服务在磁盘上保存的所有 FontCache 文件。在删除它们之前,您必须停止“Windows Presentation Foundation Font Cache”服务(或者在您的语言中称为其他名称,例如波兰语中的“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 个具有类似命名约定的文件。
在删除它们并重新启动服务之后,我的应用程序的所有版本都正常运行。没有黑屏,没有在文本框上冻结。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接