绘制图像时:System.Runtime.InteropServices.ExternalException:GDI中发生一般错误

我有一个从Panel创建的全局Graphics对象。 每隔一段时间,从磁盘中拾取一个图像,并使用Graphics.DrawImage()将其绘制到面板中。 它适用于几次迭代,然后我得到以下有用的例外:

System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI+. at System.Drawing.Graphics.CheckErrorStatus(Int32 status) at System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y) at System.Drawing.Graphics.DrawImage(Image image, Point point) 

当我完成处理图像对象时,我排除了内存泄漏。 我知道图像没有损坏,并且可以正常读取,因为程序在面板停止显示之前执行了一段时间。

我在使用PictureBox时遇到了同样的问题,但这次至少我得到了一个错误而不是什么。

我在任务管理器中检查了GDI对象和USER对象,但是当应用程序工作时它们总是大约65个用户对象和165个GDI对象。

我确实需要尽快解决这个问题,并不是说我可以在.NET系统库中粘贴断点并查看确切执行失败的位置。

提前致谢。

编辑 :这是显示代码:

 private void DrawImage(Image image) { Point leftCorner = new Point((this.Bounds.Width / 2) - (image.Width / 2), (this.Bounds.Height / 2) - (image.Height / 2)); _graphics.DrawImage(image, leftCorner); } 

图像加载代码:

 private void LoadImage(string filename, ref Image image) { MemoryStream memoryStream = DecryptImageBinary(Settings.Default.ImagePath + filename, _cryptPassword); image = Image.FromStream(memoryStream); memoryStream.Close(); memoryStream.Dispose(); memoryStream = null; } 

_image是全局的,其引用在LoadImage中更新。 它们作为参数传递,因为我想从尽可能少的地方更改全局引用,并保持其他方法自包含。 _graphics也是全球性的。

我也有一个webBrowser控件的网站,我要么一次显示图像或网站。 当有时间显示图像时,执行以下代码:

 webBrowser.Visible = false; panel.Visible = true; DrawImage(_image) _image.Dispose(); _image = null; 

_image正在引用预加载的图像。

希望这可以帮助。

你的问题与我的想法相似,但并不完全。 加载图像时,您将从MemoryStream加载它。 您必须在图像的生命周期内保持流打开,请参阅MSDN Image.FromStream 。

您必须在图像的生命周期内保持流打开。

解决方案是在FromImage函数中制作图像的副本:

 private void LoadImage(string filename, ref Image image) { using (MemoryStream memoryStream = DecryptImageBinary(Settings.Default.ImagePath + filename, _cryptPassword)) { using (tmpImage = Image.FromStream(memoryStream)) { image = new Bitmap(tmpImage); } } } 

类似于我提到的处置问题,图像似乎工作,然后当底层流被垃圾收集时随机失败。

没有更多的代码,这里没有足够的正确诊断,但是,有一点需要注意的是,您可能已经在某个时刻在图像上放置了一个绘图,并且只有在垃圾收集器运行之后才会出现代码失败了。 您是否在任何地方使用克隆图像? 令我惊讶的一件事是,如果你直接克隆一个图像,你不是克隆图像所依赖的底层位图,只是图像结构,以创建一个你需要创建的图像的正确副本新图片:

 var newImage = new Bitmap(img) 

 var newImage = oldImg.Clone(); oldImg.Dispose(); ... gr.DrawImage(newImage, new Rectangle(0,0,newImage.Width,newImage.Height); 

会工作一段时间,但随后在一些随机点失败……