【问题标题】:What happens if i don't call dispose()?如果我不调用 dispose() 会发生什么?
【发布时间】:2015-09-04 11:43:01
【问题描述】:
    public void screenShot(string path)
    {
        var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
                                        Screen.PrimaryScreen.Bounds.Height,
                                        PixelFormat.Format32bppArgb);

        var gfxScreenshot = Graphics.FromImage(bmpScreenshot);
        gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
                                    Screen.PrimaryScreen.Bounds.Y,
                                    0,
                                    0,
                                    Screen.PrimaryScreen.Bounds.Size,
                                    CopyPixelOperation.SourceCopy);

        bmpScreenshot.Save(path, ImageFormat.Png);
    }

我正在使用此代码来捕获我的计算机屏幕。

但是今天我发现有一个方法叫Bitmap.Dispose()。

何时调用 Dispose() 有什么区别?代码运行是否重要?

【问题讨论】:

  • 了解“垃圾收集器”
  • 许多 .NET 程序员从未在他们的代码中使用过 Dispose()。 Bitmap 类是一个很少有好结果的 .NET 类。他们倾向于为像素数据占用大量的非托管内存。当您创建太多屏幕截图时 Kaboom。

标签: c# bitmap dispose


【解决方案1】:

如果一个类型实现了IDisposable 接口,您绝对应该调用Dispose 方法(显式地或通过using 块)。

如果我不调用 dispose() 会发生什么?

如果你不这样做,析构函数(终结器)负责释放资源;但是,它有一些缺点:

  • 不确定:终结器由 GC 在专用线程上执行。 GC 决定何时运行它们。如果保留对对象的引用(例如,在主应用程序窗口中),则可能在您退出应用程序之前不会执行终结器。
  • 开销:除非终结器被抑制,否则 GC 会处理要销毁的对象。
  • 危险:如果终结器抛出异常,它被认为是致命的并且会导致整个应用程序崩溃。

【讨论】:

    【解决方案2】:

    必须拨打Dispose。如果不这样做,就会有一些非托管资源(例如 GDI 对象)不会被清理。这意味着你会有内存泄漏。

    是的,请致电Dispose(或更好,使用using (...) { ... })。

    【讨论】:

    • 是调用 'Dispose()' 还是使用 'using (...) { ... }' 相同?
    • @ArthurPark 是的,它们是严格等价的。请参阅stackoverflow.com/questions/10984336/… 就是说,using 是最好的,因为它已经实现了 try/finally 模式,因此即使抛出一些异常,它也能确保对象被释放。
    【解决方案3】:

    “Dispose”方法来自“IDisposable”接口并执行以下操作:

    执行与释放、释放或重置非托管资源相关的应用程序定义任务。

    基本上可以说使用的资源不会立即释放。即使不再需要它们也不会。 但只有当垃圾收集器释放它们时。

    有关更多信息,请查看 MSDN: IDisposable Interface

    关于此主题的其他有用链接:

    【讨论】:

      【解决方案4】:

      基本上你的代码应该是这样的

      public void screenShot(string path)
      {
          using (var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
                                          Screen.PrimaryScreen.Bounds.Height,
                                          PixelFormat.Format32bppArgb))
      
          {
              var gfxScreenshot = Graphics.FromImage(bmpScreenshot);
              gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
                                      Screen.PrimaryScreen.Bounds.Y,
                                      0,
                                      0,
                                      Screen.PrimaryScreen.Bounds.Size,
                                      CopyPixelOperation.SourceCopy);
      
              bmpScreenshot.Save(path, ImageFormat.Png);
          }
      }
      

      这可确保正确释放位图对象使用的非托管资源。使用单个位图,如果处理不当,您不会遇到真正的麻烦,但是一旦开始批量处理,它就变得至关重要。不正确处理会导致内存不足的问题,我已经看到内存因编码不当而很快填满。

      【讨论】:

      • 抱歉,我们同时发布了我们的答案。这是正确的答案,我会删除我的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-02
      • 1970-01-01
      • 2013-04-01
      • 2012-01-13
      • 2011-03-15
      • 1970-01-01
      相关资源
      最近更新 更多