.net 关闭并处理 - 调用哪个?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/61092/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Close and Dispose - which to call?
提问by Richard McGuire
Having read the threads Is SqlCommand.Dispose enough?and Closing and Disposing a WCF ServiceI am wondering for classes such as SqlConnection or one of the several classes inheriting from the Stream class does it matter if I close Dispose rather than Close?
已阅读线程SqlCommand.Dispose 是否足够?和关闭和处理 WCF 服务我想知道 SqlConnection 等类或从 Stream 类继承的几个类之一是否重要,如果我关闭 Dispose 而不是 Close?
回答by aku
I want to clarify this situation.
我想澄清这种情况。
According to Microsoft guidelines, it's a good practice to provide Closemethod where suitable. Hereis a citation from Framework design guidelines
根据 Microsoft 指南,Close在合适的地方提供方法是一种很好的做法。这是框架设计指南中的引文
Consider providing method
Close(), in addition to theDispose(), if close is standard terminology in the area. When doing so, it is important that you make theCloseimplementation identical toDispose...
考虑提供方法
Close(),除了Dispose(), if close 是该领域的标准术语。这样做时,重要的是使Close实现与Dispose...相同。
In most of cases Closeand Disposemethods are equivalent. The main differencebetween Closeand Disposein the case of SqlConnectionObjectis:
在大多数情况下Close和Dispose方法是等效的。的主要区别之间Close和Dispose在的情况下SqlConnectionObject为:
An application can call
Closemore than one time. No exception is generated.If you called
DisposemethodSqlConnectionobject state will be reset. If you try to call any method on disposedSqlConnectionobject, you will receive exception.
一个应用程序可以调用
Close多次。不会产生异常。如果调用
Dispose方法SqlConnection对象状态将被重置。如果您尝试调用已处理SqlConnection对象上的任何方法,您将收到异常。
That said:
那说:
- If you use connection object one
time, use
Dispose. - If connection object must be reused,
use
Closemethod.
- 如果您一次使用连接对象,请使用
Dispose. - 如果必须重用连接对象,请使用
Close方法。
回答by Brannon
As usual the answer is: it depends. Different classes implement IDisposablein different ways, and it's up to you to do the necessary research.
像往常一样,答案是:视情况而定。不同的类IDisposable以不同的方式实现,这取决于您进行必要的研究。
As far as SqlClientgoes, the recommended practice is to do the following:
就目前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
}
You shouldbe calling Dispose(or Close*) on the connection! Do notwait for the garbage collector to clean up your connection, this will tie up connections in the pool until the next GC cycle (at least). If you call Dispose, it is not necessary to call Close, and since the usingconstruct makes it so easy to handle Disposecorrectly, there is really no reason to call Close.
您应该在连接上调用Dispose(或Close*)!难道不是等待垃圾回收器来清理你的连接,这将占用连接池中,直到下一个GC周期(至少)。如果您调用Dispose,则没有必要调用Close,并且由于该using构造使其易于Dispose正确处理,因此实际上没有理由调用Close。
Connections are automatically pooled, and calling Dispose/Closeon the connection does not physically close the connection (under normal circumstances). Do not attempt to implement your own pooling. SqlClientperforms cleanup on the connection when it's retrieved from the pool (like restoring the database context and connection options).
连接会自动池化,在连接上调用Dispose/Close不会物理关闭连接(正常情况下)。不要尝试实现自己的池化。 SqlClient从池中检索连接时对连接执行清理(如恢复数据库上下文和连接选项)。
*if you are calling Close, make sure to do it in an exception-safe way (i.e. in a catch or finally block).
*如果您正在调用Close,请确保以异常安全的方式(即在 catch 或 finally 块中)执行此操作。
回答by Tyler
You DO need to call Dispose()!
你确实需要调用 Dispose()!
Dispose() is for the developer to call, the Garbage Collector calls Finalize(). If you don't call Dispose() on your objects any unmanaged resources that they used won't be disposed until the garbage collector comes around and calls finalize on them (and who knows when that will happen).
Dispose()供开发者调用,Garbage Collector调用Finalize()。如果您不在对象上调用 Dispose(),则在垃圾收集器出现并对它们调用 finalize 之前,它们使用的任何非托管资源都不会被释放(谁知道什么时候会发生)。
This scenario is called Non Deterministic Finalization and is a common trap for .net developers. If you're working with objects that implement IDisposable then call Dispose() on them!
这种情况称为非确定性终结,是 .net 开发人员的常见陷阱。如果您正在使用实现 IDisposable 的对象,则对它们调用 Dispose()!
http://www.ondotnet.com/pub/a/oreilly/dotnet/news/programmingCsharp_0801.html?page=last
http://www.ondotnet.com/pub/a/oreilly/dotnet/news/programmingCsharp_0801.html?page=last
While there may be many instances (like on SqlConnection) where you call Disponse() on some object and it simply calls Close() on it's connection or closes a file handle, it's almost always your best bet to call Dispose()! unless you plan on reusing the object in the very near future.
虽然可能有很多实例(例如在 SqlConnection 上),您在某个对象上调用 Disponse() 并且它只是在其连接上调用 Close() 或关闭文件句柄,但调用 Dispose() 几乎总是最好的选择!除非您计划在不久的将来重复使用该对象。
回答by Curt Hagenlocher
For SqlConnection, from the perspective of the connection itself, they are equivalent. According to Reflector, Dispose()calls Close()as well as doing a few additional memory-freeing operations -- mostly by setting members equal to null.
对于SqlConnection,从连接本身的角度来看,它们是等价的。根据 Reflector,Dispose()调用Close()以及执行一些额外的内存释放操作——主要是通过将成员设置为等于 null。
For Stream, they actually are equivalent. Stream.Dispose()simply calls Close().
对于 Stream,它们实际上是等效的。 Stream.Dispose()只需调用 Close()。
回答by André Chalella
This would-be quick advice became a long answer. Sorry.
这个可能的快速建议变成了一个很长的答案。对不起。
As tyler pointed out in his nice answer, calling Dispose()is a great programming practice. This is because this method is supposed to "rally together" all the resource-freeing needed so there are no unneeded open resources. If you wrote some text to a file, for example, and failed to close the file (free the resource), it will remain open and no one else will be able to write to it until the GC comes around and does what you should have done.
正如 tyler 在他的好回答中指出的那样,调用Dispose()是一种很好的编程实践。这是因为这种方法应该“团结”所有需要的资源释放,因此没有不需要的开放资源。例如,如果您向文件写入了一些文本,但未能关闭该文件(释放资源),则该文件将保持打开状态,并且在 GC 出现并执行您应该执行的操作之前,其他任何人都无法写入该文件完毕。
Now, in some cases there will be "finalizing" methods more specific to the class you're dealing with, like StreamWriter.Close(), which overrides TextWriter.Close(). Indeed they are usually more suited to the situation: a StreamWriter's Close(), for example, flushes the stream and the underlying encoder before Dispose()ing of the object! Cool!
现在,在某些情况下,将有更特定于您正在处理的类的“最终确定”方法,例如StreamWriter.Close()覆盖TextWriter.Close(). 事实上,它们通常更适合这种情况:Close()例如,StreamWriter 的 sDispose()在对象的 ing之前刷新流和底层编码器!凉爽的!
However, browsing MSDN you'll find that even Microsoft is sometimes confused by the multitude of closers and disposers. In this webpage, for instance, in some examples Close()is called before the implicit Dispose()(see using statementif you don't understand why it's implicit), and in one in particular they don't bother to. Why would that be? I too was perplexed.
但是,浏览 MSDN,您会发现即使是 Microsoft 有时也会被众多的关闭器和处理器所迷惑。例如,在此网页中,在某些示例Close()中,在隐式之前调用Dispose()(如果您不明白为什么它是隐式的,请参阅using 语句),特别是在一个示例中,它们不会打扰。为什么会这样?我也很困惑。
The reason I figured (and, I stress, this is original researchand I surely might lose reputation if I'm wrong) is that Close()might fail, yielding an exception whilst leaving resources open, while Dispose()would surely free them. Which is why a Dispose()should always safeguard a Close()call(sorry for the pun).
我想的原因(并且,我强调,这是原创研究,如果我错了,我肯定会失去声誉)是这Close()可能会失败,产生异常同时保持资源开放,同时Dispose()肯定会释放它们。这就是为什么aDispose()应该始终保护Close()呼叫(抱歉双关语)。
MyResource r = new MyResource();
try {
r.Write(new Whatever());
r.Close()
finally {
r.Dispose();
}
And yes, I guess Microsoft slipped on that one example. Perhaps that timestamp would never get flushed to the file.
是的,我猜微软忽略了那个例子。也许那个时间戳永远不会被刷新到文件中。
I'm fixing my old code tomorrow.
我明天修复我的旧代码。
Edit: sorry Brannon, I can't comment on your answer, but are you sure it's a good idea to call Close()on a finallyblock? I guess an exception from that might ruin the rest of the block, which likely would contain important cleanup code.
编辑:对不起,布兰农,我不能评论你的回答,但你确定调用Close()一个finally块是个好主意吗?我想一个例外可能会破坏块的其余部分,其中可能包含重要的清理代码。
Reply to Brannon's: great, just don't forget to call Close()when it is really needed (e.g. when dealing with streams - don't know much about SQL connections in .NET).
回复 Brannon 的:太好了,只是不要忘记在Close()真正需要时调用(例如,在处理流时 - 不太了解 .NET 中的 SQL 连接)。
回答by supercat
Typecast to iDisposable, and call dispose on that. That will invoke whatever method is configured as implementing "iDisposable.Dispose", regardless of what the function is named.
类型转换为 iDisposable,然后调用 dispose。这将调用任何配置为实现“iDisposable.Dispose”的方法,无论函数名称如何。
回答by Deep Jadia
Generally we are facing issue in Close(), Abort() and Dispose() but let me tell you difference among them.
通常,我们在 Close()、Abort() 和 Dispose() 中遇到问题,但让我告诉您它们之间的区别。
1) ABORT:- I won't suggest to use this because when abort is called the client will delete the connection without telling the server so server will wait for some amount of time (approximately 1 min). If you having bulk request then you can't use abort() because it may caused time out for your limited connection pool.
1) ABORT:- 我不建议使用它,因为当调用 abort 时,客户端将删除连接而不告诉服务器,因此服务器将等待一段时间(大约 1 分钟)。如果您有批量请求,则不能使用 abort(),因为它可能会导致您的有限连接池超时。
2) Close:- Close is very good way to closing the connection because when closing the connection it will call server and acknowledge the server to close by that side too.
2) 关闭:- 关闭是关闭连接的好方法,因为在关闭连接时,它会调用服务器并确认服务器也在该端关闭。
Here, one more thing to look. In some cases, if error generates then it is not a good way to write code in finally that connection.close() because at that time Communication State will be faulted.
在这里,还要看一件事。在某些情况下,如果发生错误,那么在 finally 那个 connection.close() 中编写代码不是一个好方法,因为那时通信状态将出现故障。
3) Dispose :- It is one type of close but after closing the connection you can not open it again.
3)处置:- 这是一种关闭,但关闭连接后,您无法再次打开它。
So try this way ,
所以试试这个方法,
private void CloseConnection(Client client)
{
if (client != null && client.State == CommunicationState.Opened)
{
client.Close();
}
else
{
client.Abort();
}
}

