使用 IDisposable 进行垃圾收集

发布于 2024-11-10 03:10:30 字数 336 浏览 1 评论 0原文

我正在和一个人谈论 using() 语句。

他说,如果我们不对像 StreamWriter 这样的东西使用 using() 语句,那么如果发生任何异常,资源将永远不会被收集。

我确实理解使用 using() 语句,但我不同意资源永远不会被收集。我认为 using() 语句最后会调用 dispose() 方法,这可以使集合更快。然而,即使我们不使用using(),也不调用dispose(),资源仍然可以通过垃圾收集来收集,尽管这可能需要更长的时间。

你同意谁的观点?

附:我知道你们都在说什么。使用 using() 语句很重要。我只是想知道如果我们不这样做的话,资源是不是就永远不会被收集到?

I was talking with a person about using() statement.

He said if we do NOT use using() statement for something like a StreamWriter, if any exception happens, the resource will NEVER get collected.

I do understand to use using() statement, but I don't agree that the resource will never be collected. I think using() statement will call dispose() method at the end, which can make the collection much faster. However, even if we don't use using(), we don't call dispose(), the resource can still be collected by gabage collection, although it may take much longer time.

Who do you agree with?

ps. I know what you all are saying. It's important to use using() statement. I just want to find out if the resource will definitely never get collected if we don't do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

风蛊 2024-11-17 03:10:30

让我们明确这一点。假设有问题的资源是文件句柄。垃圾收集器对文件句柄或如何释放它一无所知。文件句柄只是一个整数。

如果持有文件句柄的 StreamWriter 被垃圾收集,则垃圾收集器会将对象放入终结队列中。当终结队列运行时,它将调用对象的终结器,就是释放文件句柄的。

这一切都清楚了吗?垃圾收集器不会释放资源;垃圾收集器知道的唯一资源是内存中的对象。在释放对象之前,它已完成,因此对象本身知道如何释放资源。

Let's be clear on this. Suppose the resource in question is a file handle. The garbage collector knows nothing about the file handle or how to free it. The file handle is just an integer.

If the StreamWriter that is holding on to the file handle gets garbage collected then the garbage collector will put the object onto the finalization queue. When the finalization queue runs, it will call the finalizer of the object, and that is what releases the file handle.

Is that all clear? The garbage collector does not free the resource; the only resource the garbage collector knows about is objects in memory. Before the object is freed it is finalized, so it is the object itself that knows how to free the resource.

美煞众生 2024-11-17 03:10:30

using(x) 是一种确定性模式。它确保当执行流中的特定点经过时,Dispose() 在实现者上被调用。另一方面,GC 不是确定性的,因为您不知道对象何时实际被释放。 using 确保对象将在您期望的时间执行其清理代码(无论是什么),而不是在将来的某个时间。

using(x) is a deterministic pattern. It ensures that Dispose() is called on the implementor when a particular point in the execution flow is passed. The GC on the other hand is not deterministic, because you don't know exactly when the object will be actually disposed. using ensures that the object will execute its cleanup code (whatever that is) when you expect it to, rather than some time in the future.

×纯※雪 2024-11-17 03:10:30

如果不再引用该 StreamWriter,它最终将被垃圾收集,但这取决于垃圾收集器 - 它不是确定性的,因此您应该始终使用 using尽可能阻止。

If there's no reference to that StreamWriter anymore it will eventually be garbage collected, but it depends on the Garbage Collector when that is - it's not deterministic, so you should always use using blocks when you can.

零時差 2024-11-17 03:10:30

使用完 IDisposable 对象后,您应该始终调用 Dispose()using 语句是确保您遵守此规则的绝佳工具。

IDisposable 的目的是允许类处理分配的非托管资源,这些资源不会被垃圾回收自动清理。

如果在完成后使用 IDisposable 对象而不调用 Dispose(),那么您将面临永远无法正确处置资源的风险,即使在资源被垃圾回收之后也是如此。

这就是 using 语句存在的原因;它提供了使用 IDisposable 对象的便捷语法,并定义了这些对象的可用范围。

另请注意,垃圾收集器从不调用 Dispose() 本身,但另请注意,建议遵循 最终确定/处置模式,如 MSDN 上记录的。如果对象遵循 Finalize/Dispose 模式,则当 GC 调用终结器时将调用 Dispose()

You should always call Dispose() when you are done using an IDisposable object. A using statement is a great tool for making sure you obide by this rule.

The purpose of IDisposable is to allow classes to dispose of allocated unmanaged resources which will not be automatically cleaned up by garbage collection.

If you use an IDisposable object without calling Dispose() when you are done, you run the risk of never disposing of the resource properly, even after it has been garbage collected.

This is the reason why the using statement exists; it provides a convenient syntax for using IDisposable objects and defines a clear scope in which these objects are usable.

Note also that the garbage collector never calls Dispose() itself, but note also that it is recommended to follow the Finalize/Dispose pattern as documented on MSDN. If an object follows the Finalize/Dispose pattern, Dispose() will be called when the GC calls the finalizer.

弥繁 2024-11-17 03:10:30

我正在和一个人谈论 using() 语句。他说,如果我们不对像 StreamWriter 这样的东西使用 using() 语句,那么如果发生任何异常,资源将永远不会被收集。

using 语句与垃圾回收无关。一旦对象没有实时引用,它就可以进行垃圾回收。

我确实理解使用 using() 语句,但我不同意资源永远不会被收集。

哦,那你是对的。

我认为using()语句最后会调用dispose()方法,这可以使集合更快。

它可能会也可能不会使收集速度更快。 dispose 方法通常会调用 GC.SupressFinalize(object),这意味着当对象被垃圾回收时,不会调用终结器。相反,该对象将被简单地收集。所以这可以使收集速度更快。

如果您想说它会导致立即而不是稍后收集对象,那么这是不正确的。只要垃圾收集器有空,合格的对象就会被收集,以前从来没有,并且只要对象没有实时引用,它就会变得合格,而 using 语句对此几乎没有影响。实际上,由于 using 语句的finally 块包含一个实时引用,我可以想象它可能会增加对象的生命周期的场景,但这种效果不是一个考虑因素,因为控制对象的生命周期不是使用的重点。对非托管资源的确定性处置是 using 语句的要点。

但是,即使我们不使用using(),也不调用dispose(),资源仍然可以通过gabage收集来收集,尽管这可能需要更长的时间。

同样,using 和 Dispose 通常不会影响对象的生命周期。它只影响非托管资源的状态(假设正确实现了 Dispose 方法)。您是正确的,该对象仍将被收集。

I was talking with a person about using() statement. He said if we do NOT use using() statement for something like a StreamWriter, if any exception happens, the resource will NEVER get collected.

The using statement has nothing to do with garbage collection. As soon as an object has no live references it becomes eligible for garbage collection.

I do understand to use using() statement, but I don't agree that the resource will never be collected.

Oh, then you're right.

I think using() statement will call dispose() method at the end, which can make the collection much faster.

It may or may not make the collection faster. It is typical for a dispose method to call GC.SupressFinalize(object), which means that the finalizer will not be called when the object is garbage collected. Instead, the object will simply be collected. So this could make the collection faster.

If you intend to say that it causes the object to be collected immediately rather than later, then that would be incorrect. Eligible objects are collected whenever the garbage collector gets around to it, never before, and an object become eligible as soon as it has no live references, which the using statement has little effect on. Actually, since the finally block of the using statement contains a live reference, I can imagine scenerios in which it might increase the lifetime of the object, but this effect is not a consideration, since controlling an object's lifetime is not the point of a using. Deterministic disposal of unmanaged resources is the point of a using statement.

However, even if we don't use using(), we don't call dispose(), the resource can still be collected by gabage collection, although it may take much longer time.

Again, using and Dispose do not typically effect the lifetime of an object. It only affects the state of unmanaged resources (assuming the Dispose method is implemented correctly). You are correct that the object will still be collected.

染年凉城似染瑾 2024-11-17 03:10:30

using 本质上与以下内容相同(如果您怀疑,请检查两者的 IL):

 try
 { 
      IDisposable o = new Object();
 }
 finally
 {
      o.Dispose();
 }

只要有问题的对象实现了 IDisposable,就会调用 Dispose() 方法,并且资源将等待 Dispose() 中编码的一些愚蠢的东西将被垃圾收集。什么时候?这不是我能回答的问题。

是否有可能某个项目永远不会被GCed?好吧,永远不会很长一段时间,但理论上如果它超越了第一代并且只是坐在那里,那么理论上是可能的。有问题吗?不,如果最终需要内存,它将被清理。经常被错误地视为内存泄漏?最肯定的是。

using is essentially the same as the following (Check the IL of both if you doubt it):

 try
 { 
      IDisposable o = new Object();
 }
 finally
 {
      o.Dispose();
 }

As long as the object in question implements IDisposable, the Dispose() method will be called and the resource, pending something stupid coded in Dispose() will be Garbage Collected. When? Not a question I can answer.

Is it possible that an item will never be GCed. Well, never is a long time, but theoretically possible if it gets beyond the first generation and just sits there. A problem? No, if the memory is eventually needed, it will be cleaned. Often seen, incorrectly, as a memory leak? Most certainly.

抚你发端 2024-11-17 03:10:30

如果 StreamWriter 是使用 Stream 创建的,即使在 StreamWriter 被放弃之后,该 Stream 仍将被其他代码使用,则不得在 StreamWriter 上调用 Dispose。如果流在被提供给 StreamWriter 后将被其所有者放弃,那么为了正确性,必须对 StreamWriter 调用 Dispose。

回想起来,StreamWriter 可能应该有一个不执行任何操作的 IDisposable 实现,但有一个后代类 StreamOwningWriter,其实现将处理传入的流。或者,它可以有一个构造函数参数和属性来指示在调用其自己的 Dispose 方法时是否应处置该流。如果采用这些方法中的任何一种,那么正确的行为始终是在 StreamWriter 上调用 Dispose(并让“StreamWriter”(可以是 StreamWriter 或 StreamOwningWriter)担心 Dispose 是否实际上应该执行任何操作) 。

If a StreamWriter is created with a Stream that will be used by other code even after the StreamWriter has been abandoned, one must not call Dispose on the StreamWriter. If the stream will be abandoned by its owner after being given to a StreamWriter, then for correctness one must call Dispose on the StreamWriter.

In retrospect, StreamWriter should probably have had a do-nothing IDisposable implementation, but had an descendant class StreamOwningWriter whose implementation would dispose the passed-in stream. Alternatively, it could have had a constructor parameter and property to indicate whether it should dispose the stream when its own Dispose method is called. Had either of these approaches been taken, then the correct behavior would always have been to call Dispose on a StreamWriter (and let the "StreamWriter" (which could be either a StreamWriter or a StreamOwningWriter) worry about whether the Dispose should actually do anything).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文