避免处置系统定义的 Pen 和 Brush 实例

2024-03-20

我知道最好的做法是在实例上调用 Dispose()Pen http://msdn.microsoft.com/en-us/library/system.drawing.pen.aspx and Brush http://msdn.microsoft.com/en-us/library/system.drawing.brush.aspx,除非它们已设置为系统预定义的值(例如系统.绘图.画笔 http://msdn.microsoft.com/en-us/library/system.drawing.brushes.aspx, 系统.绘图.笔 http://msdn.microsoft.com/en-us/library/system.drawing.pens.aspx or 系统.绘图.系统画笔 http://msdn.microsoft.com/en-us/library/system.drawing.systembrushes.aspx)

尝试处置系统定义的资源会导致抛出异常。

如何检测(除了将 Dispose() 调用包装在 try/catch 中之外)这些资源之一是否引用系统定义的值或用户定义的值似乎并不明显。


这是我知道的一个老问题,但我一直在对涉及 GDI 对象的资源泄漏进行一些研究,并且接受的答案中几乎每个陈述都是错误的。为了让后来的读者像我一样通过搜索找到这个问题的准确性:

不需要调用 Dispose。

这种说法具有误导性。尽管从技术上讲,您可以不打电话而逃脱惩罚Dispose,不丢弃画笔或钢笔是非常糟糕的做法你拥有的一旦你完成了它。

原因是:进程中可以突出显示的 GDI 对象的数量存在硬性限制(默认设置为一万,但可以通过注册表破解来增加)——注意,不是应用程序域——并且垃圾收集器可能无法比资源泄漏的速度更快地完成资源的完成。托管内存分配产生收集压力但没有对应的最终确定压力.

垃圾收集的目的就是消除这些要求。

它不是。垃圾收集的目的是模拟具有任意多内存的环境。

主要目的之一IDisposable就是允许一个类在资源有限的环境中清理非托管资源。

这是对的。

如果您不致电Dispose()方法,一旦对象在垃圾收集期间完成并释放,该类的非托管资源将被清除。

这有时是正确的;对于 GDI 对象来说这是正确的。对于持有非托管资源的类来说,实现终结语义作为后盾是一种很好的做法;为遵循已接受答案中给出的不良建议的人提供额外的保护。你不应该依赖终结器来避免错误;你应该处置你的资源。

您应该只依靠终结器来处理疯狂的异常情况。例如考虑:

Brush myBrush = MakeMeABrush();
DoSomethingWithBrush(myBrush);
myBrush.Dispose();

假设抛出了线程中止异常after刷子的配置不过before分配给 myBrush。没有组合try-catch-finally将使您能够通过以下方式清理刷子Dispose;你必须依赖终结器。这就是终结器的用途:完全疯狂你的情况cannot处置你自己。这不是马虎的借口。

如果您“必须”调用 dispose 并且您不知道画笔实例是“系统”还是“普通”画笔,那么您将不得不使用 try...catch 块。

尽管这在技术上也是正确的,但它完全没有抓住要点。如果您不知道自己是否拥有画笔,那么您的程序设计中存在错误。不要用try-catch堵塞!修复错误!

这种情况对于所有显式管理的资源都很常见:提供资源的实体和消耗资源的实体负责清楚地记录两者中哪一个拥有清理资源。如果您不知道您是否拥有所提供的刷子,那么有人没有完成他们应该做的任务,即防止这种情况发生.

如果您决定的合同是提供资源的实体负责稍后清理它您的消费者根本不应该丢弃刷子,因为这违反了合同;如果需要的话,生产者会清理它。

如果您决定的合同是生产者和消费者都将释放资源,那么消费者必须调用Clone on every刷子传入以确保他们拥有安全可处置的资源,并且生产者也继续拥有有效的资源。

如果您决定的合同很可能是消耗资源的实体负责稍后清理它提供者必须始终为您提供可以安全处置的刷子,并且需要not自行处置资源。自从provider知道他们是自己制作刷子还是从系统获取刷子,提供者必须调用Clone()在系统刷子上获取可以安全处理的刷子,然后通过that给消费者。

但“没有人清理它,我们希望得到最好的结果”的合同是一份相当糟糕的合同。

不需要调用Dispose() on SystemBrushes and SystemPens因为 GDI+ 库会处理这些资源。

这个解释只是一个解释,实际上并没有解释任何事情。处理这些刷子之一是违法的原因是画笔的生命周期等于appdomain的生命周期.

类的备注部分将注明是否需要调用 Dispose 方法。

这种说法是错误的。您应该假设始终有必要Dispose an IDisposable资源,除非您有充分的理由不相信。文档中没有一行并不表明不需要进行处理。

以积极的方式结束:

如果我有一个图形密集型应用程序或类,那么我将缓存我需要的笔和画笔的实例。我在应用程序或类的整个生命周期中使用它们。

这是一个很好的做法。如果创建的画笔和笔的数量相对较少,并且一遍又一遍地使用相同的画笔和笔,那么永久缓存它们是很有意义的。由于它们的生命周期已到程序结束,因此无需处置它们。在这种情况下,我们不会处理垃圾,因为这不是垃圾;这很有用。 GDI 对象是not缓存当然仍然应该被处置。再次强调,追求缓存策略并不是采取不良做法的借口。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

避免处置系统定义的 Pen 和 Brush 实例 的相关文章

  • 将父控件的属性传递给子控件

    我正在为特定应用程序开发一组自定义控件 我想定义对于外观目的的控件集通用的属性 为了论证 让我们这样做CustomCtrl AccentColor 我想为我的 Windows 窗体定义相同的属性 即Form1 AccentColor当我更改
  • 从另一个 FORM 中取回隐藏的 FORM

    我有两种形式Form1 and Form2 我正在打开Form2 from Form1 on button Click Form2 obj2 new Form2 this Visible false obj2 Show 然后我想回来Form
  • DataGridView 列中的数字文本框

    我有一个DataGridView 我想要它的第一列或任何所需的列 其中有textboxes在其中 成为NUMERIC ONLY 我目前正在使用这段代码 private void dataGridViewItems EditingContro
  • 为什么有些控件同时具有BackgroundImage和Image属性?

    为什么有些控件喜欢Button or PictureBox两者都有BackgroundImage and Image财产 为什么在按钮的情况下需要它们两个 或者为什么在图片框中背景图像应该可用 BackgroundImage继承自Contr
  • 在 .NET 程序集或可执行文件中嵌入文本文件[重复]

    这个问题在这里已经有答案了 可能的重复 如何在 NET 程序集中嵌入文本文件 https stackoverflow com questions 433171 how to embed a text file in a net assemb
  • 当操作繁忙时,表单不执行任何操作(冻结)

    我有一个使用 C 的 WinForms 应用程序 我尝试从文件中读取一些数据并将其插入数据表中 当此操作很忙时 我的表单冻结并且无法移动它 有谁知道我该如何解决这个问题 这可能是因为您在 UI 线程上执行了操作 将文件和数据库操作移至另一个
  • 有没有办法禁用 .NET 标签的“双击复制”功能?

    这真的很烦人 我使用标签作为列表项用户控件的一部分 用户可以单击它来选择列表项 然后双击它来重命名它 但是 如果剪贴板中有名称 双击标签会将其替换为标签文本 我还检查了应用程序中的其他标签 双击它们也会将其复制到剪贴板 我没有在这个程序中编
  • 在 VB 2010 中禁用“默认实例”

    我已经开始在 VB 2010 中做一些基本的 win 表单工作 我真的很烦恼默认实例 https stackoverflow com q 4698538 794234特征 有没有办法可以完全禁用它并像普通类一样使用这些类 向表单的构造函数添
  • 如何使用 winforms 在 C# 中从网络下载显示下载进度的图像?

    我使用 WebRequest 从 URL 异步下载图像 如下所示 public void Download string url byte buffer new byte 0x1000 WebRequest request HttpWebR
  • WinForms:如何确定窗口是否不再活动(没有子窗口具有焦点)?

    我的应用程序使用多个窗口 我想隐藏一个特定窗口 以防应用程序失去焦点 当活动窗口不是应用程序窗口时 source https stackoverflow com questions 466354 how can i tell if a wi
  • 在 C# 中使用“using”关键字避免多次处置的最佳实践

    当变量是 IDisposable 时 我们有using关键字来管理处置 但是如果我们在方法中返回值怎么办 using twice StringContent stringToStringContent string str using St
  • GDI 函数 BitBlt 和 StretchBlt 在 Win32 中是否硬件加速?

    我似乎无法通过搜索得到明确的答案 Win32 blitting 操作是否硬件加速 GDI 而不是 GDI 我不知道这些函数如何与图形驱动程序交互 是否有任何函数调用来验证此功能 例如 GetCaps 对于特定的图形设备 win32图形设备
  • WinForm - TabStop 不工作

    我有一个带有 3 个组框的 WinForm 其中一个带有组合框 两个带有单选按钮 我将它们及其子控件全部设置为 TabStop false 但是当我使用 TAB 循环时 最后两个组框中当前选定的单选按钮将获得焦点 如果没有办法改变这种行为
  • 禁用 Windows 窗体中的关闭按钮

    我在互联网上找到了这段代码 但不确定如何使用它 我还需要在工作完成后重新启用它 请帮助 Private Const CP NOCLOSE BUTTON As Integer H200 Protected Overloads Override
  • ListView onScroll 事件

    我正在编写一个简单的 C 应用程序 我需要 Listview 上的 onScroll 事件 所以我创建了ListviewEx类继承原来的ListView 我找到了如何从 WinAPI 检测滚动消息 并修改了 WndProc 方法 现在我有这
  • 防止应用程序在控制台关闭时退出

    I use AllocConsole 在 winform 应用程序中打开控制台 如何防止应用程序在控制台关闭时退出 EDIT 不时更新的完成百分比是我想在控制台中显示的 void bkpDBFull PercentComplete obje
  • INotifyPropertyChanged 和线程

    我有一个基类实现INotifyPropertyChanged protected void OnNotifyChanged string pName if PropertyChanged null PropertyChanged this
  • 使用 JSON 序列化 PictureBox

    我正在开发一个 C Windows 窗体应用程序项目 我需要使用 JSON 序列化 PictureBox 并将其保存到文件中 由于某种原因 JSON 在尝试序列化 PictureBox 时出现错误 Newtonsoft Json JsonS
  • 如何使用 DataTable.Load(DataReader) 重新加载 DataGridView 而不出现重复记录

    任何人都可以帮助我如何避免重复输出DataGridView 这是图像变更前 https i stack imgur com CyKwY png和图像添加 编辑或删除后 https i stack imgur com Bvu0u png 这是
  • 将键码转换为相关的显示字符

    在 C Windows Forms 项目中 我有一个不提供 KeyPressed 事件的控件 它是一个 COM 控件 ESRI 映射 它仅提供 KeyUp 和 KeyDown 事件 包含关键事件参数 http msdn microsoft

随机推荐