读完线程后SqlCommand.Dispose足够吗?和关闭和处置WCF服务,我琢磨类,如SqlConnection的或几类从Stream类继承它的问题,如果我收处置,而不是关闭的一个?
根据Microsoft指南,Close
在合适的地方提供方法是一种很好的做法.这是框架设计指南的引用
考虑提供方法
Close()
,除了Dispose()
,如果收盘价在该地区的标准术语.这样做时,重要的是要使Close
实现与Dispose
... 相同.
在大多数情况下Close
,Dispose
方法是等效的.的主要区别之间Close
和Dispose
在的情况下SqlConnectionObject
为:
一个应用程序可以调用
Close
多次.没有异常生成.如果调用
Dispose
方法SqlConnection
对象状态将被重置.如果您尝试在已处置SqlConnection
对象上调用任何方法,则会收到异常.
那说:
如果您使用连接对象一次,请使用Dispose
.
如果必须重用连接对象,请使用Close
方法.
像往常一样答案是:这取决于.不同的类IDisposable
以不同的方式实现,由您来完成必要的研究.
目前SqlClient
,建议的做法是执行以下操作:
using (SqlConnection conn = /* Create new instance using your favorite method */) { conn.Open(); using (SqlCommand command = /* Create new instance using your favorite method */) { // Do work } conn.Close(); // Optional }
你应该在连接上调用Dispose
(或Close
*)!难道不是等待垃圾回收器来清理你的连接,这将占用连接池中,直到下一个GC周期(至少).如果你打电话Dispose
,没有必要打电话Close
,因为这个using
结构让它很容易Dispose
正确处理,所以没有理由打电话Close
.
连接会自动进行池化,并且呼叫Dispose
/ Close
连接不会物理关闭连接(在正常情况下).不要尝试实现自己的池. SqlClient
在从池中检索连接时对连接执行清理(如恢复数据库上下文和连接选项).
*如果您正在呼叫Close
,请确保以异常安全的方式(即在捕获或最终阻止)中执行此操作.
你需要调用Dispose()!
Dispose()供开发人员调用,垃圾收集器调用Finalize().如果你没有在你的对象上调用Dispose(),那么他们使用的任何非托管资源都不会被丢弃,直到垃圾收集器出现并调用它们(并且知道何时会发生).
此方案称为非确定性终结,是.net开发人员的常见陷阱.如果您正在使用实现IDisposable的对象,请在它们上调用Dispose()!
http://www.ondotnet.com/pub/a/oreilly/dotnet/news/programmingCsharp_0801.html?page=last
虽然可能有许多实例(比如在SqlConnection上),你在某个对象上调用Disponse(),它只是在它的连接上调用Close()或关闭文件句柄,但几乎总是调用Dispose()!除非您打算在不久的将来重复使用该对象.
因为SqlConnection
,从连接本身的角度来看,它们是等价的.根据Reflector,Dispose()
调用Close()
以及执行一些额外的内存释放操作 - 主要是通过将成员设置为null.
对于Stream,它们实际上是等价的. Stream.Dispose()
只需调用Close().
这个快速的建议成了一个很长的答案.抱歉.
正如泰勒在他的回答中指出的那样,调用Dispose()
是一种很棒的编程习惯.这是因为这种方法应该"集合"所需的所有资源释放,因此没有不需要的开放资源.例如,如果你在文件中写了一些文本,并且无法关闭文件(释放资源),那么它将保持打开状态,并且没有其他人能够写入它,直到GC到来并做你应该拥有的完成.
现在,在某些情况下,将会有更新特定于您正在处理的类的"最终化"方法,例如StreamWriter.Close()
,覆盖哪些方法TextWriter.Close()
.实际上它们通常更适合这种情况:Close()
例如,StreamWriter Dispose()
在对象进入之前刷新流和底层编码器!凉!
但是,浏览MSDN你会发现即使微软有时也被大量的关闭器和处理器搞糊涂了.例如,在这个网页中,在一些示例Close()
中,在隐式之前调用Dispose()
(如果您不理解为什么它是隐式的,请参阅using语句),特别是在一个例子中他们不打扰.那为什么会这样?我也很困惑.
我想的原因(并且,我强调,这是原始研究,如果我错了,我肯定可能会失去声誉)是Close()
可能会失败,在保持资源开放的同时产生异常,同时Dispose()
肯定会释放它们.这就是为什么一个人Dispose()
应该始终保护一个Close()
电话(对不起双关语).
MyResource r = new MyResource(); try { r.Write(new Whatever()); r.Close() finally { r.Dispose(); }
是的,我想微软在这个例子上滑倒了.也许该时间戳永远不会被刷新到文件中.
我明天要修复旧代码.
编辑:对不起布兰农,我不能评论你的答案,但你确定打电话Close()
给一个finally
街区是个好主意吗?我想这个例外可能会破坏块的其余部分,这可能包含重要的清理代码.
回答Brannon的:好的,只是不要忘记在Close()
真正需要时调用(例如在处理流时 - 对.NET中的SQL连接不太了解).