当我注意到奇怪的事情时,我一直在尝试用自定义控件识别内存泄漏:
Private f = Me.Font
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
If f IsNot Me.Font Then 'ALWAYS TRUE
f.Dispose()
f = Me.Font
End If
...
End Sub
Me.Font每次都会返回一个不同的实例,这会让我质疑我调用Me.Font的其他情况。
通常情况下这不是什么大问题,但在此控件中可以每隔500毫秒调用一次。
每次调用时都会生成Me.Font因此应该每次处理吗?有没有像这样的其他控制属性我需要警惕?
答案 0 :(得分:2)
如果您使用的是从System.Windows.Forms.Control
继承的控件而您尚未更改当前字体或默认字体,那么这似乎很合乎逻辑
如果我们查看.NET Framework Microsoft's Reference Source,我们可以看到Control.Font
property最初尝试获取控件的当前字体:
Font font = (Font)Properties.GetObject(PropFont);
if (font != null) {
return font;
}
如果没有当前字体(如果它是null
或Visual Basic中的Nothing
),它会尝试获取其父字体:
Font f = GetParentFont();
if (f != null) {
return f;
}
现在,如果控件没有父级,GetParentFont()
将返回null
(这可能会一直返回到父窗体)。如果这到达最后一个父GetParentFont()
将返回null
,从而继续执行。由于控件不是ActiveX控件,if (IsActiveX)
检查将失败并继续执行:
AmbientProperties ambient = AmbientPropertiesService;
if (ambient != null && ambient.Font != null) {
return ambient.Font;
}
我不确定这是做什么的,但即使检查失败,我们也会进入有趣的部分:
return DefaultFont;
控件返回DefaultFont
属性,如果我们go to its code:
if (defaultFont == null) {
defaultFont = SystemFonts.DefaultFont;
Debug.Assert(defaultFont != null, "defaultFont wasn't set!");
}
return defaultFont;
我们可以看到它检查控件是否已经定义了自己的默认字体,如果没有,它将返回所有标准控件的默认字体(通过SystemFonts.DefaultFont
)。
如果我们最终跳转到the code for SystemFonts.DefaultFont
,我们可以看到它会创建一个名为defaultFont
的变量,它最终会返回。
Font defaultFont = null;
现在,在查看变量的分配方式时,我们可以看到它始终会创建一个新的Font
实例(这会导致您的问题):
//Each line represents an example taken from the code.
defaultFont = new Font("MS UI Gothic", 9);
defaultFont = new Font("Tahoma", 8); //This appears two times.
defaultFont = new Font(FontFamily.GenericSansSerif, 8);
defaultFont = FontInPoints(defaultFont);
//FontInPoints only have one line: "return new Font(...);"
因此,我们现在可以得出结论,每次拨打YourControl.Font
时,如果您没有 ,它将返回新的Font
实例 分配了自定义字体/自定义默认字体, 如果所有其他检查失败 使其获得Windows的默认字体。