WPF application freezes when rendering text (wpfgf

2019-04-07 18:45发布

TL;DR:

  • application is built with WPF, running on .Net 3.5
  • newest and older versions of the app work properly on many different machines
  • on one specific machine it malfunctions in a strange way:
    • either does not start, displays black screen instead of "welcome" screen; can't do anything on that black screen
    • or does start and works properly, until a TextBox is presented and until the user starts entering the text into it; then application immediatelly hangs

Background:

I have built a WPF application on .Net 3.5. I've checked the application on various machines with different OS, ranging from Windows XP up to Windows 7 - and it runs fine, no bugs, etc. It also works fine on my client's several target machines, XP and W7 included again.

However, on one machine, it suddenly ceased to work. My client sent me the machine so I can investigate. From the files on its drives, I can see there were older versions, and they were used by the client for a few months. I also see that the newest version is not installed yet on this machine. So, I tried running the old versions first, to see what's the problem.

What user sees:

  • oldest versions (say, v1, v2) of the application does not work at all. When they start up, the only thing the application displays is ... absolutely completely black window. There should be a "welcome" screen, composed of few images and labels and a button. The app is not frozen it is "responsive" (Win7 can communicate with it, the window is not dimmed).
  • last (but not newest, let's name it v3) application runs fine, everything is clickable, features work OK, except one. When user is asked to provide a password, the user is presented with single TextBox in a popup. When the user enters at least one character in that textbox, the application freezes. It freezes even before having rendered the masked '*' of the password. The freezing is total, the application stops responding (the window is dimmed and the OS wants to close it), CPU goes to 100% (actually 50%, two-core system) and the only way to stop is kill it via task manager.
  • then I installed and tried running the newest version (v4) - it behaves just like v3 above

  • I've also tried reinstalling all the versions, just to be ensure the .EXE/.DLL files are not damaged - no changes (v1/2 - black, v3/4 - freeze on text)

Technical bits, just FYI:

  • The app is very simple, one executable with no shared libraries and no shared configuration. There is just no way the newest version could interact with old versions. Seriously, I intentionally made the app in a way it can be "just copied" and several instances can be safely kept in separate folders.
  • All versions of the app (v4, v3, v2, v1) work properly on all other machines, with various versions of Windows
  • The problem can't be related to user files or configuration, I tried copying them from problematic machine to healthy ones, and the problem does not repeat

  • Related to password box: There are absolutely no event handlers in the code that could produce a deadlock or freezing. The password textbox has no text-changed handlers. My code reads the text only after an "OK" button is pressed. The app freezes immediatelly when user enters first character, the user does not even get a chance to press "OK"

  • Related to startup: The app does almost nothing on startup. It merely displays some form of a splash/welcome screen. There is no logic there except for a nice UI and one button. The user has no chance of pressing that button. When the app starts, the screen is black and has no contents, not even the splash/welcome image.

Tracing and observations:

I've focused on the TextBox part, since it's more granular.
I've got the app to freeze again, and checked the threads with ProcessHacker.
Except for typical threads, one thread that was sitting and busy-spinning at:

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

That's certainly problem with the WPF layer itself. The DetachFromHWND tells me close to nothing, but MilGlyphRun is surely about the text rendering. It freezes while trying to render the text. I've checked the black-screens on older versions of the applications, but I couldn't catch it, since the apps were not frozen, just black.

So..

  • I've applied literally all pending updates (like, 150 of them, ~800 Mb, most of them were to the OS and .Net framework)
  • I've tried reinstalling all video drivers

No changes, still black screen, still freezing.

So, focusing back to the problem. It failed to render a text. Sounds obvious, since it deadlocked when user entered a character into a textbox, but it's damn not obvious! The user was presented with tons of different TextBoxes until he finally got to the PasswordBox. All TextBoxes worked OK, only this one fails. And why old verions of the app display black screen and the new version displays the "welcome" screen properly? How can be those issues related?

1条回答
别忘想泡老子
2楼-- · 2019-04-07 18:57

The connection is: Windows Presentation Foundation Font Cache service.

Sources:

WPF uses a Font-Cache service, running as a separate process, for, well, caching fonts. Whenever your WPF app needs to draw some text, it might ask the cache service for fonts. Once in a while the font cache might get corrupted and it then will/may randomly impact any WPF application.

Unfortunatelly, restarting the service is not enough. When this happens, you must delete all FontCache files that this service keeps on the disk. Before deleting them, you must stop the "Windows Presentation Foundation Font Cache service (or whatever it's called in your languge, for example Usługa buforowania czcionek platformy Windows Presentation Foundation in Polish..). Then, go to

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

and remove all files looking like FontCache.dat. The source articles mentioned only one file (FontCache3.0.0.0.dat, but in my case there were around 8 files with similar naming convention).

After deleing them and restarting the service, all versions of my application were running properly again. No black screens, no freezing on textbox.

查看更多
登录 后发表回答