我是否需要在托管对象上调用Dispose()?

Jul*_*les 28 .net idisposable

我无法相信我仍然对此感到困惑但是,无论如何,让我们最终指出:

我有一个类覆盖OnPaint来做一些绘图.为了加快速度,我在构造函数中预先创建了笔,画笔等,以便OnPaint不需要继续创建和处理它们.

现在,我确保我总是处理这些对象,但我感觉我不需要,因为尽管它们实现了IDisposable,但它们都是托管对象.

它是否正确?


感谢所有的答案,这个问题肯定已被钉上了.
我很高兴我一直保持警惕,总是使用'​​使用',所以我不需要经历所有的代码检查.我只想清楚我不是一个毫无意义的用户.

顺便说一句,我确实有一个奇怪的情况,最近,我不得不更换一个使用块并手动调用dispose!我会把它挖出来并创造一个新问题.

Aar*_*ght 43

这是正确的.您需要处置实现的对象IDisposable.这就是他们实现的原因IDisposable- 指定它们(直接或间接)包装非托管资源的事实.

在这种情况下,非托管资源是GDI句柄,如果在实际使用它们时未能处理它们,则会泄漏这些句柄.现在这些特定对象具有终结器,这些终结器将导致在GC启动时释放资源,但您无法知道何时会发生这种情况.从现在开始可能是10秒,可能是10天后; 如果你的应用程序没有产生足够的内存压力导致GC启动并在那些画笔/笔/字体/等上运行终结器,那么在GC实现正在发生的事情之前,你最终可能会使GDI资源的操作系统挨饿.

此外,您无法保证每个非托管包装器实际上都实现了终结器..NET Framework本身是非常一致的,因为类实现IDisposable使用正确的模式实现它,但是其他类完全可能有一个不包含终结器的破坏的实现,因此不能正确清理,除非Dispose是明确地呼吁它.一般来说,目的IDisposable是你不应该知道或关心具体的实施细节; 相反,如果它是一次性的,那么你处理它,期间.

故事的道德:总是处置IDisposable物品.如果你的类"拥有"对象IDisposable,那么它应该实现IDisposable自己.


Jam*_*ran 9

你需要处理它们.

托管对象自己管理自己的记忆.但是内存不是对象使用的唯一资源. Dispose()旨在释放其他资源.


Han*_*ant 5

你的方法有一个明显的讽刺.通过预先创建笔/画笔,您正在创建 Dispose()尝试解决的问题.那些GDI对象将会更长,就像你不调用Dispose()时一样.事实上更糟糕的是,它们至少会在表格关闭之前出现.

它们可能已经足够长,可以晋升为第二代.垃圾收集器不经常进行第2代收集,现在重要的是在它们上调用Dispose().通过将表单的Dispose()方法从Designer.cs文件移动到form.cs文件并添加Dispose调用来完成此操作.

但是,这是正确的方式.钢笔和刷子是非常便宜的物体.在Paint事件中,在需要时创建它们.并使用using语句,以便它们立即处理.使用秒表类重新确保自己这实际上不会导致任何减速.