Description
- .NET Core Version: 7.0
- Windows version: Windows 10 version 21H2 (OS Build 19044.2251)
- Does the bug reproduce also in WPF for .NET Framework 4.8?: Yes
- Is this bug related specifically to tooling in Visual Studio (e.g. XAML Designer, Code editing, etc...)? No
Problem description:
When a custom font is loaded as a Resource and used in the application, the application slowly leaks memory via an UnmanagedMemoryStream
object that grows apparently without bounds, regardless of GC collection.
The issue does not appear to affect fonts with Build Action set to Content (although publishing fonts this way may be against their respective EULAs).
Actual behavior:
When a text block is rapidly changed between a series of embedded fonts, Visual Studio's Diagnostic Tools shows a UnmanagedMemoryStream
object growing by approximately 35–40 KB per second.
Expected behavior:
Once all the custom fonts are loaded, changing the FontFamily
property of a TextBlock
shouldn't increase memory usage at all.
Minimal repro:
- Create a new WPF project (the issue can be reproduced in .NET 7.0 and .NET Framework v4.8 at least, but I can find references to it online from earlier referencing now-unavailable MS Connect posts).
- Add some typefaces to the project (I've got a combination of OTF and TTF fonts in my test app), and mark their Build Action as
Resource
. - Add those fonts to your application resources in
App.xaml
(exact code will differ based on the fonts you choose):<Application.Resources> <FontFamily x:Key="Flama">./Fonts/#Flama</FontFamily> <FontFamily x:Key="FlamaMedium">./Fonts/#Flama Medium</FontFamily> <FontFamily x:Key="IntroCaps">./Fonts/#Intro Caps</FontFamily> <FontFamily x:Key="IntroBlackInline">./Fonts/#Intro Inline Caps</FontFamily> <FontFamily x:Key="Pacifico">./Fonts/#Pacifico</FontFamily> </Application.Resources>
- In
MainWindow.xaml
, create aTextBlock
:<TextBlock x:Name="TestBlock" FontSize="48">Test block</TextBlock>
- Add a new
Loaded
event handler forMainWindow
that cycles through your embedded fonts to use as the text block's font family as fast as possible:private void MainWindow_Loaded(object sender, RoutedEventArgs e) { var resourceEnumerator = Application.Current.Resources.GetEnumerator(); var fontChanger = new DispatcherTimer(); fontChanger.Tick += (s, e) => { if (!resourceEnumerator.MoveNext()) { resourceEnumerator.Reset(); resourceEnumerator.MoveNext(); } if (resourceEnumerator.Value is FontFamily fontFamily) { TestBlock.FontFamily = fontFamily; } }; fontChanger.Start(); }
- Run the app and observe the memory usage steadily increasing over time. Diagnostic tools will show the largest culprit for the growth being the
UnmanagedMemoryStream
:
- Change the font resources to have a Build Action of
Content
, and set the Copy to Output Directory property toCopy if newer
, and re-run the test. - Observe that now the memory usage does not appear to grow over time.