在配置不同的某些机器上(操作系统,显卡和内存)我得到一个OutOfMemory异常。一些测试表明,虚拟内存消耗没有显着增加。这是引发异常的代码段:
public override Size GetPreferredSize(Size proposedSize)
{
try
{
using (Graphics g = this.CreateGraphics())
{
SizeF measured = g.MeasureString(this.Text, this.Font); // <= OutOfMemoryException
measured += new SizeF(1, 1);
return measured.ToSize();
}
}
catch (OutOfMemoryException oom)
{
System.Diagnostics.Trace.WriteLine(oom.ToString());
}
return proposedSize;
}
该类直接来自label。
CreateGraphics()调用GDI +函数GdipCreateFromHWND,在某些情况下可能会返回一个状态(3),它会引发我面对的OutOfMemoryException:
[EditorBrowsable(EditorBrowsableState.Advanced), SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
public static Graphics FromHwndInternal(IntPtr hwnd)
{
IntPtr zero = IntPtr.Zero;
int status = SafeNativeMethods.Gdip.GdipCreateFromHWND(new HandleRef(null, hwnd), out zero);
if (status != 0)
{
throw SafeNativeMethods.Gdip.StatusException(status); // status = 3 throws an OutOfMemoryException with text "Out of memory"
}
return new Graphics(zero);
}
但遗憾的是,当它返回Out Of Memory时,我没有找到关于函数和案例的文档。
这个问题至少可以在一台客户机器上快速重复。他所要做的就是单击一个按钮,该按钮创建一个新窗口,其中放置了一个派生的Label,用于在WebBrowser控件中显示内容。
如果您有任何想法可以帮助我找到异常的原因,那就太棒了!
干杯, 迈克尔
答案 0 :(得分:0)
此可能有效:
private Graphics _graphics;
protected override void OnPaint(PaintEventArgs e)
{
_graphics = e.Graphics;
base.OnPaint(e);
}
public override Size GetPreferredSize(Size proposedSize)
{
try
{
SizeF measured = _graphics.MeasureString(this.Text, this.Font);
measured += new SizeF(1, 1);
return measured.ToSize();
}
catch (OutOfMemoryException oom)
{
System.Diagnostics.Trace.WriteLine(oom.ToString());
}
return proposedSize;
}
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.creategraphics.aspx州的文档&#34;你不能缓存Graphics对象以供重用,除非使用非可视方法,如Graphics.MeasureString&#34;,这正是你想要做的。如果在绘制控件之前调用GetPreferredSize,并且您想要Dispose Graphics对象,这将失败,但这可能会帮助您更接近可行的解决方案。
答案 1 :(得分:0)
解决方法:不要使用Graphics
。如果您的应用程序在启动时运行SetCompatibleTextRenderingDefault(false)
(因为它会产生更好的文本呈现),您应该使用TextRenderer.MeasureText而不是MeasureString
,否则您将使用GDI +进行测量和GDI用于绘图会产生实际渲染和测量之间的差异。
另一种解决方案可能不是缓存Graphics
对象,而是缓存大小。由于您未使用proposedSize
,只需在Text
或Font
属性更改时测量文本,并在GetPreferredSize
中返回该缓存值。