阅读线程SqlCommand.Dispose是否足够?以及关闭和处置WCF服务我想知道诸如SqlConnection之类的类还是从Stream类继承的几个类之一,如果我关闭Dispose而不是Close会不会很重要?
阅读线程SqlCommand.Dispose是否足够?以及关闭和处置WCF服务我想知道诸如SqlConnection之类的类还是从Stream类继承的几个类之一,如果我关闭Dispose而不是Close会不会很重要?
Answers:
根据Microsoft的准则,Close在适当的地方提供方法是一种很好的做法。这是《框架设计指南》的引文
如果附近是该地区的标准术语,请考虑提供方法
Close(),除了Dispose()。这样做时,使Close实现与Dispose... 相同非常重要。
在大多数情况下Close,Dispose方法是等效的。的主要区别之间Close和Dispose在的情况下SqlConnectionObject为:
一个应用程序可以调用
Close多次。没有异常产生。如果调用
Dispose方法,SqlConnection对象状态将被重置。如果尝试在已处置SqlConnection对象上调用任何方法,则会收到异常。
说:
Dispose。Close方法。con.Open() con.Close(); 2 con.Open(); // reuse 3. con.Dispose(); // use one time con.Open(); // error
像往常一样,答案是:取决于情况。不同的类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,请确保以异常安全的方式(例如在catch或finally块中)进行操作。
conn.Close(); // Optional这不是可选的。这是多余且不必要的。您将对象处置两次,某些代码分析工具会将其标记为警告。
using (var x = ..) { x.Dispose(); },在这种情况下x确实是“配置两次”。
您确实需要调用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()几乎总是您的最佳选择!除非您计划在不久的将来重用该对象。
Dispose。
Dispose() using()IDisposableusing()Dispose()Close()Open()
Close连接,Postgres自动设置连接标识符null。从那里开始,不能Dispose使用已经设置为的sql连接标识符null。
对于SqlConnection,从连接本身的角度来看,它们是等效的。根据Reflector的说法,Dispose()调用Close()以及执行一些其他的释放内存的操作-主要是将成员设置为等于null。
对于Stream,它们实际上是等效的。 Stream.Dispose()只需调用Close()。
Component那里继承而来的,它似乎没有做任何尝试Close()。我看不到任何地方DBConnection或SqlConnection与这些通知有关的任何地方。但是,它确实有一个私有资源DisposeMe(),在任何地方都没有引用。
这可能很快就会成为一个很长的答案。抱歉。
正如tyler在他的好答案中指出的那样,调用Dispose()是一种很棒的编程习惯。这是因为该方法应该“聚集在一起”释放所有需要的资源,因此不需要多余的开放资源。例如,如果您向文件中写入了一些文本,但未能关闭文件(释放资源),则该文件将保持打开状态,直到GC出现并执行您应做的一切之前,其他任何人都无法写入该文件。完成。
现在,在某些情况下,将针对您正在处理的类(例如StreamWriter.Close())覆盖更具体的“完成”方法TextWriter.Close()。确实,它们通常更适合这种情况:Close()例如,StreamWriter的StreamWriter Dispose()在对象被放入之前先刷新流和基础编码器!凉!
但是,浏览MSDN时,您会发现,即使是Microsoft,有时也会因大量的关闭器和处置器而感到困惑。例如,在此网页中,在某些示例Close()中,在隐式代码之前调用Dispose()(如果您不理解为什么它是隐式的,请参阅using语句),尤其是它们不会打扰。为什么会这样呢?我也很困惑。
我认为(并且我强调,这是原始研究,如果我错了,我肯定会失去声誉)的原因是,它Close()可能会失败,产生一个例外,同时保持资源开放,同时Dispose()肯定会释放它们。这就是为什么a Dispose()应该始终维护Close()呼叫的原因(对双关语很抱歉)。
MyResource r = new MyResource();
try {
r.Write(new Whatever());
r.Close()
finally {
r.Dispose();
}
是的,我想微软会漏掉一个例子。也许该时间戳永远不会刷新到文件中。
我明天要修正旧代码。
编辑:对不起布兰农,我不能对你的解答发表评论,但你确定这是一个好主意,调用Close()一个上finally块?我猜一个例外可能会破坏其余的块,其中可能包含重要的清理代码。
回答Brannon的问题:太好了,只是别忘了Close()在确实需要时调用它(例如,在处理流时-对.NET中的SQL连接了解不多)。
将类型转换为iDisposable,然后对其进行调用处理。这将调用配置为实现“ iDisposable.Dispose”的任何方法,而与函数的名称无关。
IDisposable.Dispose,但这并不意味着它就是名称。请注意,在vb.net中,可以将一个函数绑定到多个接口成员,而这些接口成员的名称不必与该函数的名称相关。
using (myObj as IDisposable)
通常,我们在Close(),Abort()和Dispose()中面临问题,但让我告诉您它们之间的区别。
1)ABORT:-我不建议使用此方法,因为当调用abort时,客户端将删除连接而不通知服务器,因此服务器将等待一段时间(大约1分钟)。如果您有批量请求,则不能使用abort(),因为它可能会导致有限的连接池超时。
2)关闭:-关闭是关闭连接的好方法,因为关闭连接时,它将调用服务器并确认服务器也在该侧关闭。
在这里,还有另一件事要看。在某些情况下,如果产生错误,则不是在该connection.close()中最终编写代码的好方法,因为那时通讯状态将出错。
3)处置:-这是一种关闭方式,但是在关闭连接后无法再次打开它。
因此,尝试这种方式,
private void CloseConnection(Client client)
{
if (client != null && client.State == CommunicationState.Opened)
{
client.Close();
}
else
{
client.Abort();
}
}
client != null不正确/具有误导性,因为它不能保护所有用法。另外,我不确定代码如何达到“此连接未打开且应关闭”的状态。