c# - 参数无效异常和 ResourceManager

标签 c# memory-leaks gdi+ embedded-resource

我编写的 Winforms .Net 4 应用程序的客户端现在经常报告由于“参数无效”错误而导致的崩溃。

所有“图像”实际上都是很小的资源图标(16x16 像素),而且数量不多。它们都是通过资源管理器检索的,并且几乎所有它们都通过设计器生成的代码分配给按钮

每当我使用 ResourceManager 检索图标资源时,ResourceManager 似乎都会实例化一个新的位图。所以这些都没有明确处理。

我已经尝试查看 GDI 对象的数量和用户句柄的数量。句柄的数量是稳定的,GDI 对象的数量似乎在缓慢增加:在我打开/关闭(和处置)应用程序中的模态窗体后,还有一些在使用。

  • 是否由于 GDI 对象的数量太多而导致参数无效?
  • 如果是,是否是由 ResourceManager 引起的?
  • 我是否必须明确释放资源管理器创建的资源?
  • 如果不是,Parameter is not valid 是从哪里来的?

在这里,当我在 toolstripmenuitem 上更改显示的图标时

System.ArgumentException: Parameter is not valid.
   at System.Drawing.Image.get_RawFormat()
   at System.Windows.Forms.ToolStripItem.set_Image(Image value)

对应代码:

tsbExpand.Image = global::MyProject.Properties.Resources.arrow_in;

这是一个用来显示图标的图片框

System.ArgumentException: Parameter is not valid.
  at System.Drawing.Image.get_FrameDimensionsList()
  at System.Drawing.ImageAnimator.CanAnimate(Image image)
  at System.Drawing.ImageAnimator.ImageInfo..ctor(Image image)
  at System.Drawing.ImageAnimator.Animate(Image image, EventHandler   onFrameChangedHandler)
  at System.Windows.Forms.PictureBox.Animate(Boolean animate)
  at System.Windows.Forms.PictureBox.Animate()
  at System.Windows.Forms.PictureBox.OnParentChanged(EventArgs e)
  at System.Windows.Forms.Control.AssignParent(Control value)
  at System.Windows.Forms.Control.ControlCollection.Add(Control value)

对应代码:

this.pcbIcon.Image = global::MyProject.Properties.Resources.information;

谢谢

编辑 19/02

我记得我在下面添加了一段代码(取自 http://www.codeproject.com/Tips/513764/Repainting-WinForms-windows-safely-inside-a-proces ) 之前注意到增加了Parameter is not valid 的问题。我不确定这是否相关

public static class WinFormUtils
{
   /// <summary> Processes all Paint events only </summary>
   public static void DoPaintEvents()
   {
       //MessageFilter registration
       Application.AddMessageFilter(PaintMessageFilter.Instance);
       //Process messages in the queue
       Application.DoEvents();
       //MessageFilter desregistration
       Application.RemoveMessageFilter(PaintMessageFilter.Instance);
   }

   /// <summary> Custom message filter </summary>
   private class PaintMessageFilter : IMessageFilter
   {
       static public IMessageFilter Instance = new PaintMessageFilter();

       #region IMessageFilter Members

       /// <summary> Message filter function </summary>
       public bool PreFilterMessage(ref System.Windows.Forms.Message m)
       {
               return (m.Msg != 0x000F); //WM_PAINT -> we only let WM_PAINT messages through
       }

       #endregion
   }
}

编辑 27/10/2016:参数无效确实是由上面的代码引起的。因此,如果您不知道自己在做什么,请不要乱用 Windows 消息!

最佳答案

Is the parameter not valid due to the number of GDI objects being to high?

是的,很有可能。异常的质量很差,GDI+ 不会生成好的错误代码。 “参数无效”并不意味着比“它不起作用”更多。 GDI 对象过多或桌面堆空间不足是“它不起作用”的主要原因。

If yes, is it caused by the ResourceManager?

不完全是。当您获得图像资源时,您就成为该对象的所有者。调用它的 Dispose() 方法是您的工作。很少这样做,实际上也不会造成麻烦。除非您创建的程序永远不会对 GC 堆施加足够的压力。那种使用大量控件和图形但不管理大量数据的程序。如果您没有获得足够的 gen#2 集合,那么这些对象的终结器将不会运行,并且 native 操作系统对象也不会被销毁。

Do I have to explicitly release the resources created by the resource manager?

是的。

任务管理器中的 GDI 对象计数器可以让您保持诚实。别忘了看看另一个典型的麻烦制造者 USER Objects。定期调用 GC.Collect() 是快速修复 GDI 对象计数的方法。如果您只是没有使用足够的 GC 堆,这并非不合理。总是从内存分析器那里获得第二意见,它最清楚,当我们看不到报告时,我们只是在猜测它。

关于c# - 参数无效异常和 ResourceManager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35103187/

相关文章:

c# - EF4 : Why does proxy creation have to be enabled when lazy loading is enabled?

java - "Do not place Android context classes in static fields; this is a memory leak"- 静态 View 的 Lint 警告

.net - 检测图像是否为空的有效方法

image - 如何在Delphi中用alpha透明度绘制透明?

iphone - App delegate 分配的对象显示在多个 subview 中?

c++ - GDI+ - 将位图像素转换为 JPG 格式

c# - 我引用了一个常量类静态变量,但是当我这样做时,值会以某种方式改变

c# - MVC 3,url参数不分开

c# - Visual Studio 2012 网络共享

c - 从 C 中的 DLL 函数返回 char 缓冲区而不产生内存泄漏