处置框架对象 [英] Disposing framework objects

查看:53
本文介绍了处置框架对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在论坛上听过很多关于.NET内存管理的讨论和

处理事情,敲定它们,垃圾收集等等。我的问题是

哪些托管类型在使用后需要处理,并且为什么只需让垃圾收集器完成其工作就可以了,而不用担心

关于调用Dispose ?是否有一般规则,大多数不需要明确处理,除了这里和那里有例外?或者另一种方式

左右?


克里斯

I''ve heard a lot of talk on the forum about memory managment in .NET and
disposing things, finalizing them, garbage collection, etc. My question is
which managed types need to be disposed after being used, and for which is
it OK to simply let the garbage collector do its work, without worrying
about calling Dispose? Is there a general rule that most don''t need to be
explicitly disposed, with an exception here and there? Or the other way
around?

Chris

推荐答案

那个'不一定是真的。 SqlConnection类实现了

IDisposable,但不需要处理。调用Close方法

足以关闭连接并释放资源。


另一个例子:DataSet类。这也不需要处理。


我认为垃圾收集器收集对象时需要Dispose

没有释放资源,然后它叫Dispose来做

这个。例如,如果你忘了关闭你的SqlConnection,当

垃圾收集器运行时,它会调用Dispose,这会释放连接。

当然,直到它运行,你的连接只是闲逛,这个

是开发人员应该明确地调用Close的原因。

" Jon Skeet" < SK *** @ pobox.com>在消息中写道

新闻:MP ************************ @ news.microsoft.com ...
That''s not necessarily true. The SqlConnection class implements
IDisposable, but does not need to be disposed. Calling the Close method is
enough to close the connection and release resources.

Another example: DataSet class. This does not need to be disposed either.

I think Dispose is needed when the garbage collector is collecting objects
that have not had their resources released, then it calls Dispose to do
this. For example, if you forgot to close your SqlConnection, when the
garbage collector runs, it calls Dispose, and this releases the connection.
Of course, until it runs, your connection is just hanging around, and this
is why the developer should call Close explicitly.

"Jon Skeet" <sk***@pobox.com> wrote in message
news:MP************************@news.microsoft.com ...
Chris Capel< ch *** @ nowhere.com>写道:
Chris Capel <ch***@nowhere.com> wrote:
我在论坛上听到很多关于.NET中的内存管理和处理事物,最终确定它们,垃圾收集等的讨论。我的问题
是否需要在使用后处理哪些托管类型,并且
可以简单地让垃圾收集器完成其工作,而不必担心调用Dispose?是否有一般规则,大多数不需要明确处理
,除此之外有例外?或者反过来呢?
I''ve heard a lot of talk on the forum about memory managment in .NET and
disposing things, finalizing them, garbage collection, etc. My question is which managed types need to be disposed after being used, and for which is it OK to simply let the garbage collector do its work, without worrying
about calling Dispose? Is there a general rule that most don''t need to be explicitly disposed, with an exception here and there? Or the other way
around?



如果某些东西实现了IDisposable,请将其处理掉。如果没有,那么它就不需要处理了。

-
Jon Skeet - < sk *** @ pobox.com>
http://www.pobox.com/~skeet/
如果回复小组,请不要给我发邮件



If something implements IDisposable, Dispose it. If not, then it
doesn''t need disposing.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet/
If replying to the group, please do not mail me too



Jon Skeet写道:

[snip]
Jon Skeet wrote:
[snip]
另一个例子:DataSet类。这也不需要处理
Another example: DataSet class. This does not need to be disposed
either.



我认为这样做是个好主意。它不会造成任何伤害,事实上它可能会使垃圾收集更快,因为它可以取消注册实例以进行最终确定。



I think it would be a good idea to do so though. It can''t do any harm,
and in fact it''s likely to make garbage collection quicker, as it can
unregister the instance for finalization.




我同意如果你想要最好的性能(内存占用和速度),你最好在带有终结器的类型上调用Dispose()。由于这个事实以及因为我还没有讨论GC的所有含义,我只是非常强烈支持Call Dispose()可能"政策

直到最近。

但是,凭借几千行的经验,我慢慢地肯定地说,b $ b得出的结论是这个政策经常使你的代码混乱

比其他任何东西(>我编写的代码的99%不是

性能至关重要)。我甚至认为我用这种方式引入了更多错误。

我今天写的以下真实代码代表了一个很好的例子:

例如:


public void Log(string eventLogMsg)

{

MemoryStream stream = new MemoryStream();


//将eventLogMsg添加到流和重置位置

long origin = stream.Position;

StreamWriter writer = new StreamWriter(stream);

writer.Write(eventLogMsg);

writer.Flush();

stream.Position = origin;


//读取流入DataSet

StreamReader reader = new StreamReader(stream);

DataSet dataSet = new DataSet();

dataSet.ReadXml(reader) ;


// ...

}


eventLogMsg包含一条XML消息,我需要阅读到dataSet,

然后用于进一步处理。虽然我可能错过了更容易实现相同的方法,但我确实声称这是完全合理的代码。

两个月前,我会编写相同的功能如下:


public void Log(string eventLogMsg)

{

using(MemoryStream stream = new MemoryStream())

{

//将eventLogMsg添加到流和重置位置

long origin = stream.Position;

using(StreamWriter writer = new StreamWriter(stream))

{

writer.Write(eventLogMsg);

}

stream .Position = origin; // BOOM


//将数据流读入DataSet

DataSet dataSet = new DataSet();

using(StreamReader reader =新的StreamReader(流))

{

dataSet.ReadXml(读者);

}


// ...

}

}


问题是,这个函数在尝试时总会抛出异常

重置Stream.Position属性,这不是很明显

,除非你知道StreamWriter.Dispose()也在流上调用Close()

我们传递给它的构造函数。


当然,有些情况下你绝对需要调用Dispose()或

你的程序根本就不会表现如预期的那样(如下所述:
http://groups.google.com/groups?hl=e...ng.google.com)

但是,我相信这些情况比那些天真的程序员可能会过早地调用Dispose()而引入错误的情况更为罕见

(Jeffrey Richter)在他的优秀书籍应用.NET框架编程中,C sharp中的
声音类似的问题)。


问候,


安德烈亚斯



I agree that you''d better call Dispose() on types with finalizers if you
want the best performance (both memory footprint and speed). Because of this
fact and also because I hadn''t yet grocked all the implications of GC, I was
a very strong advocate of the "Call Dispose() whenever possible" policy
until recently.
But, with a few thousand lines of experience behind me, I slowly but surely
come to the conclusion that following this policy often clutters your code
more than anything else (>99% of the code I write is not
performance-critical). I even think that I introduced more bugs this way.
The following real world code, which I have written today, makes for a good
example:

public void Log( string eventLogMsg )
{
MemoryStream stream = new MemoryStream();

// add eventLogMsg to stream and reset position
long origin = stream.Position;
StreamWriter writer = new StreamWriter( stream );
writer.Write( eventLogMsg );
writer.Flush();
stream.Position = origin;

// read stream into DataSet
StreamReader reader = new StreamReader( stream );
DataSet dataSet = new DataSet();
dataSet.ReadXml( reader );

// ...
}

eventLogMsg contains an XML message, which I need to read into dataSet,
which is then used for further processing. While I might have missed easier
ways to achieve the same, I do claim that this is perfectly reasonable code.
Two months ago, I would have written the same function as follows:

public void Log( string eventLogMsg )
{
using( MemoryStream stream = new MemoryStream() )
{
// add eventLogMsg to stream and reset position
long origin = stream.Position;
using ( StreamWriter writer = new StreamWriter( stream ) )
{
writer.Write( eventLogMsg );
}
stream.Position = origin; // BOOM

// read stream into DataSet
DataSet dataSet = new DataSet();
using( StreamReader reader = new StreamReader( stream ) )
{
dataSet.ReadXml( reader );
}

// ...
}
}

Problem is, this function will invariably throw an exception when it tries
to reset the Stream.Position property, which is not immediately obvious
unless you know that StreamWriter.Dispose() also calls Close() on the stream
object we passed to its constructor.

Sure, there are situations where you absolutely need to call Dispose() or
your program would simply not behave as expected (as was discussed here:
http://groups.google.com/groups?hl=e...ng.google.com).
However, I believe these situations are more rare than the ones where a
naive programmer could introduce a bug with calling Dispose() too early
(Jeffrey Richter in his excellent book "Applied .NET framework programming
in C sharp" voices similar concerns).

Regards,

Andreas


Andreas Huber< ah **** @ gmx.net>写道:
Andreas Huber <ah****@gmx.net> wrote:
我认为这样做是个好主意。它不会造成任何伤害,事实上它可能会使垃圾收集更快,因为它可以取消注册实例以进行最终确定。
I think it would be a good idea to do so though. It can''t do any harm,
and in fact it''s likely to make garbage collection quicker, as it can
unregister the instance for finalization.


直到最近。
但是,凭借几千行的经验,我慢慢地肯定地得出结论,遵循这一政策往往会使你的代码混乱。其他任何事情(我编写的代码的99%都不是性能至关重要的)。我甚至认为我用这种方式引入了更多的错误。
我今天写的以下真实代码就是一个很好的例子:



I agree that you''d better call Dispose() on types with finalizers if you
want the best performance (both memory footprint and speed). Because of this
fact and also because I hadn''t yet grocked all the implications of GC, I was
a very strong advocate of the "Call Dispose() whenever possible" policy
until recently.
But, with a few thousand lines of experience behind me, I slowly but surely
come to the conclusion that following this policy often clutters your code
more than anything else (>99% of the code I write is not
performance-critical). I even think that I introduced more bugs this way.
The following real world code, which I have written today, makes for a good
example:




< snip>


我认为你的例子只表明你应该知道Dispose是什么,b $ b可能会做什么 - 我会一直考虑你之前的代码

有点怀疑。


由于性能原因,处理不仅仅是必要的,而且我认为它是

总是更安全地妥善处理 - 知道会发生什么。

我会坚持处理。


-

Jon Skeet - < sk *** @ pobox.com>
http://www.pobox.com/~skeet/

如果回复该群组,请不要给我发邮件



<snip>

I think your example only shows that you should know what Dispose is
likely to do - and I would always have considered your previous code
somewhat suspect.

Dispose isn''t just necessary for performance reasons, and I think it''s
always safer to dispose appropriately - knowing what''s going to happen.
I''ll stick by always disposing.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet/
If replying to the group, please do not mail me too


这篇关于处置框架对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆