我记得我是通过将它从网络直接流式传输到位图来加载图像。关闭流,返回位图并将其保存在图像控件中。
我除了当我执行= loadPicture()时,第一个位图将被释放,就像智能指针在C ++中一样。但它没有,我消耗了很多公羊,直到我打电话给处理。所以我的问题是。
GC和Dispose able对象如何在C#中运行?为什么它不像smart_ptr那样实现?
答案 0 :(得分:8)
引用不是智能指针。让引用变量超出范围,将其替换为另一个值,和/或将其设置为null都完全 nothing 。
这只是CLI / GC设计的一部分......
Gargage Collection(GC)将在需要时运行 ,并且应该清理所使用的托管内存,并且(如果提供了终结器)也可以清除任何非托管资源。但对于确定性清理:这是IDisposable
的全部目的。当你完成它们时,Dispose()
这些对象是你的工作 - 通过using
,或者把它交给承担这个责任的其他东西(常见的,例如,使用流/读者等)
using (StreamReader reader = new StreamReader(myfile)))
{
...
}
答案 1 :(得分:2)
当运行时认为有必要时,GC会启动。
基本规则是:当你使用Disposable类型(IDispose)时,你(作为程序员)应该尽快释放该类型使用的资源,当你不再需要使用它时调用Dispose类型。 例如,当您读取文件时,您在阅读完文件后立即关闭该文件。 (在这种情况下,呼叫关闭也会调用dispose。)
答案 2 :(得分:1)
您必须在实现IDisposable的任何对象上调用Dispose explicity,否则您的非托管资源将不会被释放。如果您不想将其称为明确,那么您必须覆盖Finalize方法以调用Dispose方法 - 这就是您经常会看到这一点的原因:
class MyClass : IDisposable
{
...
~MyClass()
{
this.Dispose(false);
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{ /* dispose managed stuff also */ }
/* but dispose unmanaged stuff always */
}
}
答案 3 :(得分:0)
smart_ptr是引用计数。虽然当它们不再被任何代码引用时,它允许确定性地释放它们的资源,但它们确实存在它们自己的问题:分配引用总是需要更新计数器,循环引用无法自动释放导致内存泄漏,内存管理器被更频繁地调用。
.NET中的GC是一个全面的收集器。它始于任何时候它感觉应该释放内存(通常由一些内存使用情况触发,但不是确定性),并通过构建系统中所有实时引用的列表(包括CPU寄存器中的内容,嵌套引用等)开始)。这是有效的,因为我们处于无法进行指针运算等的托管环境中 - 系统可以跟踪所有引用。在构建了实时引用列表之后,它基本上释放了所有未知的内存。当然,这只是基本的草图,对于非托管资源的效率和管理,它更像是对象生成,终结器等,但这对于它如何工作的基本理解并不重要。
IDisposable接口用于实现一次性模式,这有助于在处理应以确定方式处置的对象时使用。该模式是在不再需要对象时显式调用Dispose(),因此释放非托管资源或关闭句柄等,但不释放其内存。这将在稍后由GC完成,但是后来发生这种情况并不重要,因为已经执行了资源的确定性释放。