我需要调用Graphics.Dispose()吗?

6
在我创建一个新的位图图像的VB.NET程序中,我调用Graphics.FromImage来获取一个Graphics对象来在位图上绘制。然后将图像显示给用户。
我看到的所有代码示例都会对Bitmaps和Graphics对象调用.Dispose()方法,但是当它们都没有触及磁盘上的文件时,是否有必要这样做呢?这些对象可能会获取其他未被垃圾收集器清除的非托管资源吗?
5个回答

6

在需要使用它的范围内,将其包装在using语句中。然后不必担心显式调用Dispose()

伪代码:

using(new Graphics() = Graphics.FromImage)
{
     //Magic happens...
}

6

是的。

任何实现IDisposable接口的对象都需要调用Dispose()方法。图形对象使用的GDI句柄是非托管的,当您完成使用它们时需要进行处理。

最佳实践是使用using块进行封装。顺便提一下,关于这个主题已经有几个SO问题了。


抱歉如果这是一个重复的问题。我没有看到任何与这个特定情况相关的内容,想知道在这种情况下会使用哪些(如果有)非托管资源。 - alnorth29

1

是的,您应该调用Dispose。它与触摸磁盘无关;它与使用需要正确释放回操作系统的非托管资源有关。在Graphics对象的情况下,我会假设它分配了设备上下文句柄,当它们不再需要时应该释放。


1

Dispose() 的规则是,如果你创建了一个 IDisposable 对象,那么你应该调用它。最好的方法是在 using 块或 finally 中调用。

也许你不需要这样做,但 Dispose() 会决定是否需要。

如果你得到了一个对象,但没有调用构造函数,则需要查看返回它的方法的文档,以确定它是否希望你调用 Dispose() 或者它会自己调用。


准确地说,适当使用 using(请参见其他答案)隐式执行 Dispose,因此您不需要自己调用它。 - ToolmakerSteve

0

图形实现了IDisposable接口, 因此您应该调用Dispose方法以确保清理非托管资源。

非托管资源不由垃圾收集器处理,因此必须手动处理。这通常通过Dispose()方法完成,以便在定义良好的时间点提供清理。它也可以通过finalizer处理,但在这种情况下,资源将被使用更长的时间。

确保在所有情况下调用Dispose的最简单方法是使用using构造。例如:

using(var g = Graphics.FromImage()) {
    // use the resource 
} 

“必须手动处理”并不完全正确,正如您稍后所写的那样。适当实现 IDisposable 应该确保即使没有手动(在您的代码中)释放也能保证安全。 - Maciej
如果你在谈论自己的类,那么是的,但是所有的.NET框架中的IDisposable类最终都会被处理,即使你在代码中没有调用Dispose方法。 - Maciej
@MaciejDopieralski:仅通过实现“IDisposable”接口并不能使对象被处理。您需要显式地调用“Dispose”方法或使用“using”语句块来释放资源。如果该类型还实现了终结器,那么终结器可能会自动调用“Dispose”方法,但这并不改变开发人员必须处理此问题的事实,这使其与GC自动清理托管内存的方式不同。 - Brian Rasmussen
1
就此前述的来回讨论中的混淆,值得一提的是Brian没有区分处理非托管资源的类的设计者必须要做什么——第二段“非托管资源...,以及该类的客户端需要做什么——“确保调用Dispose”。 - ToolmakerSteve
@BrianRasmussen - 调用Dispose是一个好主意,因为它可以确定性地释放非托管资源;但是Finalizer应该正确实现IDisposable模式,以便如果没有显式调用Dispose(using语句只是语法糖)... 最重要的是,对于设计良好的类,Dispose方法将在垃圾回收期间(最终)被调用。 - David V. Corbin
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接