【发布时间】:2014-11-07 11:34:51
【问题描述】:
TL;DR:
- 应用程序使用 WPF 构建,在 .Net 3.5 上运行
- 最新和旧版本的应用程序可以在许多不同的机器上正常运行
- 在一台特定的机器上,它以一种奇怪的方式出现故障:
- 两者都不启动,显示黑屏而不是“欢迎”屏幕;在那个黑屏上什么都做不了
- 或确实启动并正常工作,直到出现 TextBox 并且用户开始在其中输入文本;然后应用程序立即挂起
背景:
我在 .Net 3.5 上构建了一个 WPF 应用程序。我已经检查了具有不同操作系统的各种机器上的应用程序,从 Windows XP 到 Windows 7 - 它运行良好,没有错误等。它在我客户的几台目标机器上也能正常工作,再次包括 XP 和 W7。
但是,在一台机器上,它突然停止工作。我的客户把机器寄给我,这样我就可以调查了。从其驱动器上的文件中,我可以看到有较旧的版本,它们被客户使用了几个月。我还看到最新版本尚未安装在这台机器上。所以,我先尝试运行旧版本,看看有什么问题。
用户看到了什么:
- 应用程序的最旧版本(例如 v1、v2)根本无法运行。当它们启动时,应用程序显示的唯一内容是......绝对完全黑色的窗口。应该有一个“欢迎”屏幕,由少量图像和标签以及一个按钮组成。该应用程序未冻结,它是“响应式”的(Win7 可以与其通信,窗口未变暗)。
- 最后一个(但不是最新的,我们将其命名为 v3)应用程序运行良好,一切都可点击,功能正常,除了一个。当要求用户提供密码时,会在弹出窗口中向用户显示单个
TextBox。当用户在该文本框中输入至少一个字符时,应用程序会冻结。它甚至在呈现密码的蒙面“*”之前就冻结了。完全冻结,应用程序停止响应(窗口变暗并且操作系统想要关闭它),CPU 达到 100%(实际上是 50%,双核系统)并且唯一的方法stop 是通过任务管理器杀死它。 然后我安装并尝试运行最新版本 (v4) - 它的行为就像上面的 v3 一样
我还尝试重新安装所有版本,只是为了确保 .EXE/.DLL 文件没有损坏 - 没有更改(v1/2 - 黑色,v3/4 - 冻结文本)
技术位,仅供参考:
- 该应用程序非常简单,一个没有共享库和共享配置的可执行文件。只是没有办法最新版本可以与旧版本交互。说真的,我故意让应用程序可以“直接复制”,并且可以将多个实例安全地保存在不同的文件夹中。
- 应用程序的所有版本(v4、v3、v2、v1)在所有其他计算机上都能正常运行,以及各种版本的 Windows
问题与用户文件或配置无关,我尝试将它们从有问题的机器复制到健康机器,问题不再重复
与密码框相关:代码中绝对没有可能产生死锁或冻结的事件处理程序。密码文本框没有文本更改处理程序。我的代码只有在按下“确定”按钮后才会读取文本。当用户输入第一个字符时,应用程序立即冻结, 用户甚至没有机会按“确定”
- 与启动有关:应用程序在启动时几乎什么都不做。它仅显示某种形式的启动/欢迎屏幕。除了漂亮的 UI 和一个按钮外,没有其他逻辑。用户没有机会按下该按钮。应用启动时,屏幕是黑色的,没有任何内容,甚至没有启动画面/欢迎图像。
追踪与观察:
我专注于 TextBox 部分,因为它更细化。
我让应用程序再次冻结,并使用 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 工作正常,只有这个失败。为什么旧版本的应用程序显示黑屏,而新版本的应用程序正常显示“欢迎”屏幕?这些问题怎么可能相关?
【问题讨论】:
标签: wpf windows caching fonts text-rendering