调用Dispose()后图标仍然可用?

时间:2011-08-16 13:01:55

标签: c# .net-2.0

我一直在尝试使用Dispose正确地解决我们的一些代码,这些代码在很多地方都被搁置了。一旦这样的实例是图标,我注意到我觉得奇怪的东西,如果我打电话Icon.Dispose()我仍然可以使用图标。

所以我将它解压缩到一个我完全希望崩溃的小控制台应用程序(抛出一个ObjectDisposedException),但它没有...我错误地理解了应该在这里做什么?

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;

namespace DisposeTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Icon icon = new Icon(@"C:\temp\test.ico");
            icon.ToBitmap().Save(@"C:\temp\1.bmp");
            icon.Save(new FileStream(@"C:\temp\1.ico", FileMode.OpenOrCreate, FileAccess.ReadWrite));
            icon.Dispose();
            GC.Collect(); // Probably not needed, but just checking.
            icon.Save(new FileStream(@"C:\temp\2.ico", FileMode.OpenOrCreate, FileAccess.ReadWrite));
            icon.ToBitmap().Save(@"C:\temp\2.bmp");
        }
    }
}

4 个答案:

答案 0 :(得分:8)

  

我将它解压缩到一个我完全希望崩溃的小控制台应用程序中,但事实并非如此。我错误地理解了应该在这里做什么?

包含错误编程实践的程序不会必需崩溃和刻录。如果他们这样做肯定是好的,但他们没有必要。据我所知,文档没有声明“如果使用处理图标,程序崩溃”是库的支持功能,所以你不能依赖它。

(如果文档确实说某处你发现了一个错误;如果你想在Connect上报告它,那将不胜感激。)

对于人们似乎觉得有趣的相关问题,请参阅关于在C中利用非崩溃行为的问题:

Can a local variable's memory be accessed outside its scope?

最后,您的评论是正确的,注意垃圾收集器可能不相关。请记住,“Dispose”的目的是丢弃非托管资源。垃圾收集器的目的是丢弃托管内存并通过终结器丢弃非托管资源。由于图标的内存仍处于活动状态(处理器可能无论如何都会抑制终结),因此强制进行垃圾回收不太可能。

答案 1 :(得分:6)

它不会崩溃,因为Dispose()方法在您的情况下不执行任何操作。 Icon类包装器可以包装两个不同的图标数据源。在您的情况下,图标数据来自文件并存储在byte []中。这不是需要处理的系统资源,垃圾收集器已经处理好了。

其他图标数据源来自Windows句柄。相当罕见,但是当你使用Icon.FromHandle()或其中一个System.Drawing.SystemIcons时你会得到它。现在它确实包装了一个非托管资源,使得使用Dispose()很有用。

这种模式并不罕见。还有很多情况下Dispose()被继承到一个没有多大意义的类中。像MemoryStream或BackgroundWorker。无论如何,传统的智慧是处置它们。

答案 2 :(得分:4)

这种行为,虽然有点奇怪,但确实有道理。通常,Dispose()用于释放非托管资源;这是一种与系统中的其他进程“玩得很好”的方法。在这种情况下,您可能会在HICON期间发布Dispose()句柄。与Icon关联的其他(托管)资源(包括实际的byte[]数据)将在收集托管对象时发布。

你尝试通过调用GC.Collect()来做到这一点,但这不会做任何事情,因为Icon仍然存在:它被称为icon的局部变量引用,并且是目前没有资格收集。

答案 3 :(得分:0)

查看using语句。每次创建实现IDisposable的对象时都应该使用它。它确保正确处理对象,即使抛出异常也是如此。

http://msdn.microsoft.com/en-us/library/yh598w02.aspx