绘制图像时:System.Runtime.InteropServices.ExternalException:GDI 中发生一般错误
我有一个从面板创建的全局 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 正在引用预加载的图像。
希望这有帮助。
I've got a global Graphics object created from a Panel. At regular intervals an image is picked up from the disk and drawn into the panel using Graphics.DrawImage(). It works fine for a few iterations and then I'm getting the following helpful exception:
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)
I ruled out memory leaks as I dispose of the image object when I'm done with it. I know that the images are not corrupted and can be read fine as the program executes fine for a while before the panel stops showing.
I ran into the same problem when using a PictureBox but this time at least I got an error instead of nothing.
I checked the GDI objects and USER objects in the Task Manager but they're always around 65 user objects and 165 GDI objects when the app works and when it doesn't.
I do need to get to the bottom of this as soon as and it's not like I can stick breakpoints in .NET System libraries and see where exactly execution fails.
Thanks in advance.
EDIT: This is the display code:
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);
}
the image load code:
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 is global and its reference is updated in LoadImage. They are passed as parameters as I want to change the global references from as few places as possible only and keep the other methods self contained. _graphics is also global.
I've also got a webBrowser control for web sites and I either show an image or a website at one time. when there's time to display an image, the following code executes:
webBrowser.Visible = false;
panel.Visible = true;
DrawImage(_image)
_image.Dispose();
_image = null;
_image is referencing a pre-loaded image.
Hope this helps.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你的问题和我的想法很相似,但又不完全一样。当您加载图像时,您是从 MemoryStream 加载它。您必须在图像的生命周期内保持流打开,请参阅 MSDN Image.FromStream 。
解决方案是在 FromImage 函数中复制图像:
与我提到的处理问题类似,图像似乎可以工作,然后当底层流被垃圾收集时随机失败。
Your problem is similar to what I thought, but not quite. When you are loading the image, you are loading it from a MemoryStream. You have to keep the stream open for the lifetime of the image, see MSDN Image.FromStream.
The solution is to make a copy of your image in the FromImage function:
Similar to the dispose problem I mentioned, the image will seem to work and then randomly fail when the underlying stream is garbage collected.
如果没有更多的代码,这里还不足以正确诊断,但是,需要注意的一件事是,您可能已经在早些时候的某个时刻处理了绘图的图像,并且只有在垃圾收集器运行您的代码之后正在失败。您是否在任何地方使用克隆图像?我惊讶地了解到的一件事是,如果您直接执行 克隆图像,您不是克隆图像所依赖的底层位图,而是克隆图像结构,要创建图像的正确副本,您必须创建一个新图像:
这
将适用于虽然,但随后在某个随机点失败......
Without a little more code there is not enough to properly diagnose here, however, one thing to look at is that you may have disposed on the image your a drawing with at some point earlier and it is only after the garbage collector runs that your code is failing. Are you using cloned images anywhere? One thing I was suprised to learn is that if you do a straight clone of an image, you are not cloning the underlying bitmap that the image rely's upon, only the image structure, to create a proper copy of an image you have to create a new image:
as
will work for a while, but then fail at some random point...