参数无效异常和ResourceManager

时间:2016-01-30 14:50:35

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

我写的Winforms .Net 4应用程序的客户端现在经常报告崩溃,因为'参数无效'错误。

所有'图像'实际上都是小资源图标(16x16像素),并没有那么多。它们都是使用资源管理器检索的,并且几乎所有这些都是通过设计器生成的代码分配给按钮

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

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

  • 由于GDI对象的数量很高,参数无效吗?
  • 如果是,是否由ResourceManager引起?
  • 我是否必须明确释放资源管理器创建的资源?
  • 如果否,参数无效的来源是什么?

这时我正在更改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)在注意到参数增加之前是无效问题。我不确定这是否相关

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消息!

1 个答案:

答案 0 :(得分:-1)

  

由于GDI对象的数量很高,参数是否无效?

是的,这很有可能。异常的质量很差,GDI +不会产生良好的错误代码。 “参数无效”并不仅仅意味着“它不起作用”。由于有太多的GDI对象或用完桌面堆空间是主要的“它没有用”的原因。

  

如果是,是否由ResourceManager引起?

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

  

我是否必须明确释放资源管理器创建的资源?

任务管理器中的GDI对象计数器是让您诚实的。别忘了还要看另一个经典麻烦制造者USER Objects。定期调用GC.Collect()是GDI对象计数的快速修复。如果你没有使用足够的GC堆,那就不合理了。总是得到内存分析器的第二意见,它最了解我们只是在我们看不到报告时猜它。