【问题标题】:Disposing objects added using AddValue of SerializationInfo处理使用 SerializationInfo 的 AddValue 添加的对象
【发布时间】:2010-09-13 14:23:49
【问题描述】:

如何确保我添加到 SerializationInfo 对象中的对象得到处置?

例如:如果我向 info 对象添加一个哈希表,我如何确保在序列化之后,没有对我的类的 hastable 对象的活动引用并且我可以以某种方式释放内存?

info.AddValue("attributesHash", attributesHash, typeof(System.Collections.Hashtable));


更新(代码)

[Serializable]
class A : System.Runtime.Serialization.ISerializable
{
    List<int> m_Data = new List<int>();
    //...
    public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
    {
        if (m_Data != null)
        {
            info.AddValue("MyData", m_Data, typeof(List<int>));
            m_Data.Clear();
        }
        m_Data = null; // <-- Will this be collected by GC?
        GC.GetTotalMemory(true); //forced collection
    }
};

我的问题是:如果我在添加到信息列表后使我的对象为空,它会在调用序列化后被释放(当信息被破坏时 - 我希望),或者在调用 GC 的函数时(我希望不这么认为)?

如果设置'm_Data = null'不会把它标记为垃圾,那我怎么知道m_Data占用的内存已经被释放了呢?

【问题讨论】:

  • 这个问题没有意义,垃圾收集器管理内存,而不是你。序列化程序完成后不会保留引用。
  • 我只是想知道它是否存在......如果是,那么直到什么时候。谢谢
  • 您显示的代码严重错误。调用 AddValue() 将复制您的 m_data 引用,但序列化机制在 GetObjectData 返回之后才真正使用此引用 - 但您在下一行清除此集合 - 所以您总是序列化一个空集合。
  • 嗯.. 这是否意味着该引用的副本没有临时保存到集合中?我想,我正在将引用传递到集合中。因此,应该有两个对象指向相同的数据,其中之一是 m_Data。如果我将 m_Data 设置为 null,那么另一个仍在引用该内存位置,对吗?

标签: c# memory serialization memory-management


【解决方案1】:

“我可以以某种方式释放内存”和“对象被丢弃”不太好。

内存管理由 GC 完成。一旦不再引用一个对象,它就会被标记为垃圾回收。所以它处理托管资源。

然而,Disposing 是完全不同的动物,它在实现 IDisposable 的类型上调用 Dispose() 并处理非托管资源,例如文件句柄和 Windows 资源。

你需要明确你的意思。

【讨论】:

  • 好答案!我知道这一点..但不知何故没有正确地提出问题。 :) 我只想知道添加到信息列表的对象是否保存在内存中。如果是,直到什么时候 - 直到序列化?
  • 谢谢!您似乎正在尝试添加未实现 IDisposable 的 Hashtable,对吗?那么你关心的是 IDisposable 还是 GC?
【解决方案2】:

您需要使您的包含对象实现 IDisposable。但仅仅因为你已经被序列化并不意味着你也需要被处置。如果这是预期的,那么引用对象应该在序列化之后调用 dispose。

对于反序列化的对象,它也应该在使用完成时被任何引用它的对象处理(大概在另一个应用程序域中?)。所以这意味着这两个实例都需要被处理掉。如果您共享的资源是单个实例(例如 IntPtr),那么您可能需要更聪明地处理它,例如不要使用此对象处理该非托管资源,而是从更高级别处理。

一般经验法则:谁创造它,谁处置它。

IDisposable documentation 描述的另一种常见模式是将 Dispose() 调用放入对象析构函数中。这将为您的处置提供不确定的时间,但可以保证工作(假设您没有参考泄漏)。

【讨论】:

  • 感谢您提供参考建议。但也许我没有正确地提出我的问题。我已经更新了这个问题。我想要的只是要释放的内存-无论哪种方式都有效:)
【解决方案3】:

经过大量分析,我认为 GC 在请求时不会收集内存……至少在 GetTotalMemory 函数的情况下不会。

将对象设置为 null 会将其标记为垃圾,但这并不意味着它会立即被收集。

【讨论】:

  • 将 m_data 引用设置为 null 没有任何作用,因为 info 仍在范围内,并且您刚刚要求它(通过 AddValue)维护对 m_data 所引用的同一集合的引用。跨度>
  • 没错!因此,当 'info' 集合被释放时,对对象的最后一个引用也应该被销毁并且 GC 应该释放对象的内存。那是我的问题/困惑。
猜你喜欢
  • 2013-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多