【问题标题】:ValueType Not Getting Garbage Collected?ValueType 没有收集垃圾?
【发布时间】:2014-05-09 12:41:54
【问题描述】:
 public struct LocalTLS : IDisposable
{
    public byte[] bArr;
    public string str;
    public LocalTLS(int k)
    {
        str = "Labamba";
        bArr = new byte[20000];
    }
    public void Dispose()
    {
        MessageBox.Show("In Dispose");
        //Thread.FreeNamedDataSlot("jaja");
        int k = 90;
        k += 90;
    }
} 
private void buttonTLS_retreive_Click(object sender, EventArgs e)
{
        LocalTLS lts = new LocalTLS(1);
}

点击事件返回后,我期待 Dispose 调用,但永远不会发生,有人可以解释一下。我不想执行任何手动步骤,例如调用 Dispose 或使用。我希望它自动发生。

感谢您的所有回答,我想为 LocalDataStoreSlot 实现一个类,它将自动释放 Slot 并超出范围,如注释代码所示。这将使开发人员无需记住 调用 dispose,其中实际的 FreeNamedDataSlot(...) 发生。好像是不可能的

【问题讨论】:

  • 这是我唯一的后续问题:你知道何时以及如何使用IDisposable吗? Here's a link, just in case
  • 您能解释一下为什么您希望在事件返回后调用 Dispose 方法吗?
  • 我希望 Dispose 调用,但永远不会发生 - 预期的行为,您的期望完全错误。 =D
  • Dispose() 在 lts 超出范围时不会自动调用。手动调用它或将其包装在“使用”块中。

标签: c# collections garbage


【解决方案1】:

CLR 不会一直执行垃圾回收,否则你的程序会很慢,因为它正在执行 GC。为了执行 GC,CLR 必须在回收范围外对象使用的内存之前挂起所有线程。这是一个非常大的性能影响。

CLR 将执行 GC 并在必要时调用对象的 Dispose 方法。除非有充分的理由,否则不要调用对象的 Dispose() 方法。如果对象与本机系统句柄、网络连接、文件句柄等相关联,那么这些都是使用using 关键字或将其称为Dispose() 方法的好理由。通常,CLR 会足够快地 GC 超出范围的对象,这样您的应用程序就不会耗尽内存。

我理解您的担忧,您认为 byte[20000] 对您的应用程序来说是一个重要的内存占用,并且您希望仔细控制您的内存使用。但这不是 C++。 CLR 会自动为您管理内存。在我过去 7 年的 .NET 开发中,我只遇到过一个应用程序,其中默认 GC 不够快,我必须手动调用对象上的 Dispose()。所以简而言之,只需将内存管理交给 CLR - 它做得非常好。

附言如果你对 GC 内部的工作原理感兴趣,网上有很多深入的文章。只需搜索 - 你会找到它们。

【讨论】:

    【解决方案2】:

    您必须像这样将对象声明包装在 using 中:

    using(LocalTLS lts = new LocalTLS(1))
    {
       // use lts here
    
    } // at this point, the Dispose method is called.
    

    或者手动调用Dispose方法:

    lts.Dispose();
    

    此外,当代码中没有引用 lts 时,垃圾收集器会自动调用 Dispose() 方法。

    【讨论】:

    • 如果我不想使用 using 怎么办,因为我可能正在修改值
    • @Dr.sai,请参阅我的答案的最后一行
    • 我也不想调用 dispose,如果 Microsoft 说它们将被自动收集,那么我希望在 Dispose 上调用,谢谢
    • Nope dispose 永远不会被调用,因为该消息框永远不会出现
    • @Dr.sai 这就是 Amit 试图告诉你的 - 它不会被调用。您需要使用 using 块或自己调用它。这就是它的工作原理。它不是析构函数。
    【解决方案3】:

    它是一个结构,它存在于内存堆栈而不是内存堆上。所以它不会像对象那样被车库收集器收集,所以 GC 不会调用 dispose 方法。当您的方法结束时,您的结构“LocalTLS”将被释放并从内存堆栈中取出。执行此操作时,它不会查找 IDisposable 接口。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-18
      • 2011-10-12
      • 1970-01-01
      • 1970-01-01
      • 2011-01-21
      • 1970-01-01
      相关资源
      最近更新 更多