【发布时间】:2015-08-27 07:37:35
【问题描述】:
我正在测试我的 Windows 窗体用户控件。当应用程序负载很高时(例如应用程序占用超过 1 GB),它会抛出 Out of memory 或 Argument invalid 异常。
这里是用缓冲区绘制控件的代码,
protected override void OnPaint(PaintEventArgs e)
{
if (m_buffer == null || m_Redraw)
{
if (m_buffer != null)
m_buffer.Dispose();
m_buffer = new Bitmap(Width, Height);
using (Graphics g = Graphics.FromImage(m_buffer))
{
DrawUserControl(g, ClientRectangle);
}
m_Redraw= false;
}
e.Graphics.DrawImage(m_buffer, Point.Empty);
base.OnPaint(e);
}
内存不足异常发生在e.Graphics.DrawImage(m_buffer, Point.Empty);
new Bitmap(Width, Height);出现参数无效异常
注意:仅当应用程序负载超过 1 GB(例如 1.5 GB,2GB RAM)。
不带缓冲的绘制控件不会抛出任何异常但会导致闪烁效果。这是没有缓冲的代码
protected override void OnPaint(PaintEventArgs e)
{
this.SuspendLayout();
DrawUserControl(e.Graphics, ClientRectangle);
this.ResumeLayout();
base.OnPaint(e);
}
我希望我的控件在高负载下呈现而不会闪烁。我不希望应用程序由于我的控制而中断。请分享您的建议
与缓冲相关的编辑:
1) 缓冲区图像不会在所有绘制事件期间创建。如果需要重新绘制控件,它将在第一次创建。否则,将在控件上绘制现有的缓冲区图像。这样可以避免不必要的控件重绘
2) 如果控件需要重新绘制,将使用新的位图,因为现有缓冲区图像的大小和控件的当前大小可能会有所不同。即使我使用现有图像,参数无效抛出异常
尝试使用 BufferedGraphicsContext
根据@taffer 的回答,我尝试使用BufferedGraphicsContext。它还会引发内存不足异常。我在下面发布堆栈跟踪
System.ComponentModel.Win32Exception (0x80004005):存储空间不足 可用于处理此命令 在 System.Drawing.BufferedGraphicsContext.CreateCompatibleDIB(IntPtr hdc, IntPtr hpal, Int32 ulWidth, Int32 ulHeight, IntPtr& ppvBits)
在 System.Drawing.BufferedGraphicsContext.CreateBuffer(IntPtr src, Int32 offsetX, Int32 offsetY, Int32 width, Int32 height)
在 System.Drawing.BufferedGraphicsContext.AllocBuffer(Graphics targetGraphics, IntPtr targetDC, Rectangle targetRectangle)
在 System.Drawing.BufferedGraphicsContext.AllocBufferInTempManager(图形 targetGraphics, IntPtr targetDC, 矩形 targetRectangle) 在 System.Drawing.BufferedGraphicsContext.Allocate(Graphics targetGraphics, Rectangle targetRectangle)
【问题讨论】:
-
尽量避免一次全部加载?部分加载并与启动画面结合?
-
您不需要在每次绘制时都处理和重新创建缓冲区。清除它。
-
创建一个位图是昂贵的 ..你这样做,可能每秒数百次。将缓冲区分配到任何高流量区域之外。
-
此外,大多数控件都有一个双缓冲标志,您可以通过 Control.SetStyle 在 .ctor 中设置。
-
旁注:
SuspendLayout()和ResumeLayout()与绘画无关。绘制控件不应该触发LayoutEvent,否则你的控件会很慢。您应该删除这些行。
标签: c# winforms out-of-memory doublebuffered