【问题标题】:.net disposing of image resources in forms.net 以表单形式处理图像资源
【发布时间】:2017-02-14 17:57:39
【问题描述】:

当我的表单引用图像和图标资源时,我有点困惑是否要处理它们。具体来说,如果我从设计时资源中引用图像/图标或在运行时加载图像,行为是否会有所不同。 (.Net4, VS2015, C#)

显然,如果您在设计时将表单的 Icon 属性设置为 Resource,则在关闭表单时您不会显式地Dispose() 。但是如果你这样设置呢:

this.Icon = Resources.my_default_icon;

您是否必须在关闭该表单时处理 this.Icon

同样,如果我有一个仅用于“品牌化”的迷你类,并且有一个静态 Icon 对象在运行时加载(可能来自文件,可能只是引用嵌入式资源)怎么办?我应该在静态Icon 的吸气剂中使用复制构造函数吗?还是可以将其设为公共静态 Icon 并允许我的所有表单在其 _Shown() 事件中具有以下单行符?

this.Icon = MyBrandingClass.formIcon;

不确定它是否有很大不同,我看到了一些关于在运行时设置图片框的图像并处理图像的参考,但是你会处理嵌入的资源图像吗?如果我传递了对我的品牌形象的引用,我可以/应该省略 dispose 吗?或者我应该在 getter 中使用复制构造函数来返回一个新的 Image 对象,然后在处理完表单后总是将其丢弃?

【问题讨论】:

  • 几乎普遍适用于 .NET 的 GC 的经验法则是您只处置您创建的对象。如果您没有创建该对象,那么您不应该处置它。您的嵌入式资源也是如此。你没有创建对象,所以你不应该处理它们。
  • 我想你已经知道答案了。想象一下,Form.Dispose() 方法确实释放了 Icon 对象,这对您的徽标来说不是一个令人讨厌的惊喜吗?正常的所有权规则适用,Form 类没有创建图标对象,因此也无法释放它。几乎没有人编写代码来处理它。这么小的对象无关紧要,GC 会处理它。而且,如果您无法跟踪使用它的表单数量,那么您当然不会打扰。如果它是一个巨大的喇叭位图,会变得更加不确定,然后你开始喜欢它的 Clone() 方法。

标签: c# .net winforms


【解决方案1】:

程序应在不再需要图像时将其处理掉,但这并不一定意味着需要您的代码执行此操作。

在你的第一个例子中:

this.Icon = Resources.my_default_icon;

这实际上转发到ResourceManager 类的静态实例。查看 Resources.Designer.cs 中的代码,您可能会发现它提供了丰富的信息。

您可以将该类视为“拥有”图像。它最初会创建对图像的引用,因此会在 ResourceManager 的实例被销毁时(即程序退出时)处理它

您的第二个示例实际上非常相似:

this.Icon = MyBrandingClass.formIcon;

您正在自己实现类似于 ResourceManager 的东西。

在这种情况下,将 MyBrandingClass 视为图像的所有者,因此负责清理它。如何?使 MyBrandingClass 成为具有静态实例的单例。这样,当程序终止时,MyBrandingClass 的析构函数就可以释放它在其生命周期内实例化的任何资源。

您可以考虑的其他事情是让您的 MyBrandingClass 从 ResourceManager 继承。或者,也许您可​​以只拥有多个 ResourceManagers 实例(假设您计划拥有不同版本的 MyBrandingClass)。正如我所说,查看 Resources.Designer.cs 中的文档和代码可能会让您了解实际发生的内部情况,并为您提供可能在运行时填充 ResourceManager 的想法(可能来自a directory of images?)

如果在设计时所有资源都已知,则另一个选择是在您的项目中拥有多个 Resources 对象。右键单击项目,添加新项目,选择“资源文件”。然后,您可以使用适合每个品牌的内容填充每一个,并在应用程序启动时初始化对正确的引用。这将使您的可执行文件膨胀,因为您包含每个品牌的所有资源,即使您只使用一个。如果您想更改品牌或添加新品牌,它还需要重新构建应用程序,因此在运行时从目录动态填充资源管理器可能会更好(尽管会使安装程序打包更复杂一些)。

【讨论】:

  • 你是对的。我正在为几个字符串、一个图标和一个图像创建一个非常有限的 ResourceManager。所有都是静态对象,并加载到我的类的静态构造函数中。鉴于它们因此应该像嵌入式资源一样可用 - 在执行的整个生命周期内 - 你认为我需要担心任何清理吗?或者如果我不这样做,如果有非托管资源等待处置,程序会在某些情况下挂起吗?
  • 老实说:我会担心清理工作。这是一种很好的做法,如果您将来扩展您的程序,您可能会非常高兴。例如。在开发环境中,您可能想在不关闭应用程序的情况下切换品牌以查看其工作原理?那么清理可能会很好!我更新了我的答案,进一步了解在设计时使用多个资源文件。
【解决方案2】:

如果您有一个类(ResourcesMyBrandingClass),则该类应在这些资源超出范围时处理其资源。

对于Resources,这并不是你真正的工作,而且可能不是一个大问题,因为该类的范围应该是流程执行的持续时间。

对于MyBrandingClass,听起来您在使用它的方式类似——静态类在您的流程中终生存在。如果不是这样,您应该适当地处置这些资源。

一般来说,IDisposable 应该用于垃圾收集器无法自行获取的托管资源,并且应该在进程执行结束之前释放以释放资源。您的 Icon 资源可能就是这样的资源 - 但同样,在您的程序执行期间也可能需要它。如果你在执行过程中将其丢弃并再次使用它,你几乎肯定会遇到异常。

【讨论】:

    【解决方案3】:

    您不处置嵌入的资源,除非您确定不再需要该资源。如果品牌形式不再显示,那么处置可能是可以的。复制构造函数太过分了,并不能解决任何问题。

    嵌入的图标不会引起太大的问题。我有数百个,它工作正常。切记不要保留大的 bmp。

    【讨论】:

      猜你喜欢
      • 2018-08-28
      • 1970-01-01
      • 2013-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多