Should I dispose of the old font when changing the font of a control?

浪尽此生 提交于 2019-12-12 16:15:24

问题


C#, Windows Forms app.

We're re-skinning our application and I'm also changing the awful default font we used in the old one. So I thought I'd call the following function to change the font of all controls on a form when the form is loaded.

  internal static void SetFonts(Control control)
  {
    Font oldFont = control.Font;
    if (oldFont.Name != GlobalFontName)
    {
      string familyName = GlobalFontName;
      Font newFont = new System.Drawing.Font(familyName,
        oldFont.Size, oldFont.Style, GraphicsUnit.Point, 0);
      control.Font = newFont;
      //oldFont.Dispose();
    }
    foreach (Control child in control.Controls)
      SetFonts(child);
  }

I thought it would keep resources down if I disposed of the old font after reassigning the control with the new one, but on closing the form I'm receiving access violation exceptions from one control type from a set of third party controls. If I comment out the line "oldFont.Dispose()" then I don't get the exception.

Is this a bug of the third party control set or is this to be expected?
Memory wise, can I get away with not explicitly disposing of the old font (The app runs on kiosks for 12hr+ a day) ?


回答1:


Don't dispose of the old Font, that's the job of the Control whose font you're changing. Also, use tools such as GDIView to monitor your handles (such as fonts).




回答2:


Control fonts are very weird, as a consequence of the fact that a Font object actually encapsulates two different things:

  1. Information about typeface, typestyle, etc.
  2. A GDI font handle.

The latter aspect of a Font object encapsulates a resource; the former does not. Calling Dispose on a Font object releases the latter, but does not destroy the former.

While I don't think I've seen their behavior "officially" documented anywhere, it seems that the built-in controls are never actually drawn using the Font object that was used to set the Font property; instead, they use the attributes of the assigned Font object to generate a new GDI font object and then use that to draw the control. Although calling Dispose on a font object will make it unusable as an argument to DrawString or other such methods, it will not prevent its use as a "template" for making new font objects.

A consequence of this is that controls don't care if the assigned Font object is disposed (whether before or after it's assigned), nor do they ever dispose it. Reading the Font property from a control will always return the same Font object that was last assigned to it, without regard for whether that Font object was disposed. Consequently, it seems that if nothing will ever read a control's Font property and expect to draw with it, the safest way to assign a control's Font property without a temporary resource leak would be the very-bizarre-looking:

using f = new Font(...)
  theControl.Font = f;

That's arguably safer than reading the control's Font property and disposing that before assigning the new value, since the using approach above knows that the Font which is assigned to the control won't be used for anything else, while the latter approach can't know whether the same Font is used by some other code that would object to its disposal.

I really wish MS had documented how Font resources are supposed to be handled. Unfortunately, so far as I know they haven't.




回答3:


I decided to store the created fonts into a list as they were created and dispose of them during form.Dispose(). But on some windows I got errors doing this too.

What I've just realized is that the third party control must also be changing it's fonts during skinning/painting, so my font in the list was no longer valid for a control and may have been disposed by GC.

So storing the fonts for later disposal doesn't appear to be safe, and I wondered then if I should instead store controls that had had their fonts changed.

By this time the prospect of continuing along this line lost its attractiveness and instead I've manually gone through all 200+ forms in my app with search/replace instead lol

Im not very pleased.



来源:https://stackoverflow.com/questions/29103522/should-i-dispose-of-the-old-font-when-changing-the-font-of-a-control

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!