C# 绳子似乎粘得太长了

C# 绳子似乎粘得太长了,c#,string,memory-management,garbage-collection,C#,String,Memory Management,Garbage Collection,简而言之,我有一个将平面数据文件转换为XML文件的应用程序。它通过填充对象,然后将它们序列化为XML来实现这一点 我遇到的问题是垃圾收集器似乎没有处理序列化字符串。3500记录文件在完成之前运行到OutOfMemoryExceptions。确实有些可疑 当我将序列化从混合中去掉并只传递一个空字符串时,内存消耗仍然如预期的那样,因此我排除了中间对象(平面文件和xml之间)是问题所在的可能性。它们似乎是按预期收集的 有人能帮忙吗?如何确保正确处理这些字符串 更新:一些示例代码 // myObj.Se

简而言之,我有一个将平面数据文件转换为XML文件的应用程序。它通过填充对象,然后将它们序列化为XML来实现这一点

我遇到的问题是垃圾收集器似乎没有处理序列化字符串。3500记录文件在完成之前运行到OutOfMemoryExceptions。确实有些可疑

当我将序列化从混合中去掉并只传递一个空字符串时,内存消耗仍然如预期的那样,因此我排除了中间对象(平面文件和xml之间)是问题所在的可能性。它们似乎是按预期收集的

有人能帮忙吗?如何确保正确处理这些字符串

更新:一些示例代码

// myObj.Serialize invokes an XmlSerializer instance to handle its work    
string serialized = myObj.Serialize();
myXmlWriter.WriteRaw(serialized);
这基本上就是问题所在——如果我将字符串
序列化
退出,内存问题也会消失,即使我仍在将平面文件转换为对象,一次一个

更新2:序列化方法

public virtual string Serialize()
{
      System.IO.StreamReader streamReader = null;
      System.IO.MemoryStream memoryStream = null;

      using (memoryStream = new MemoryStream())
      {
          memoryStream = new System.IO.MemoryStream();
          Serializer.Serialize(memoryStream, this);

          memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
          using (streamReader = new System.IO.StreamReader(memoryStream))
          {
              return streamReader.ReadToEnd();
          }
      }
}

您是否有一个代码示例—如何创建这些字符串?您是否在任何地方闯入非托管代码(这意味着您需要自己清理代码)


另一个想法是如何将平面数据文件转换为XML。根据构建文件的方式,XML可能会有点繁重。如果您试图将整个对象保存在内存中,很可能(事实上很容易做到)内存不足。

您是否有代码示例-如何创建这些字符串?您是否在任何地方闯入非托管代码(这意味着您需要自己清理代码)


另一个想法是如何将平面数据文件转换为XML。根据构建文件的方式,XML可能会有点繁重。如果您试图将整个对象保存在内存中,很可能(事实上很容易做到)内存不足。

您需要确保它们没有被引用到任何地方。在抛出OutOfMemoryException之前,将运行GC。如果它没有恢复记忆,那就意味着某些东西仍在保留它。正如其他人所说,如果您发布一些代码,我们可能会提供帮助。否则,您可以使用探查器或WinDbg/SOS来帮助确定字符串中包含的内容。

您需要确保它们不会在任何地方被引用。在抛出OutOfMemoryException之前,将运行GC。如果它没有恢复记忆,那就意味着某些东西仍在保留它。正如其他人所说,如果您发布一些代码,我们可能会提供帮助。否则,您可以使用探查器或WinDbg/SOS来帮助找出字符串上的内容。

确实很奇怪。每次序列化记录写入XmlWriter后,我都添加了以下内容:

if (GC.GetTotalMemory(false) > 104857600)
{
     GC.WaitForPendingFinalizers();
}

你难道不知道吗,它一直在控制着它,它的处理过程中没有任何意外,从来没有超过我设定的阈值。我觉得应该有更好的方法,但似乎代码执行得太快,垃圾收集器无法及时回收字符串。

确实很奇怪。每次序列化记录写入XmlWriter后,我都添加了以下内容:

if (GC.GetTotalMemory(false) > 104857600)
{
     GC.WaitForPendingFinalizers();
}

你难道不知道吗,它一直在控制着它,它的处理过程中没有任何意外,从来没有超过我设定的阈值。我觉得应该有一个更好的方法,但似乎代码执行得太快了,垃圾收集器无法及时回收字符串。

看起来您的方法确实可以清理为:

public virtual string Serialize()
{
    StringBuilder sb = new StringBuilder();
    using (StringWriter writer = new StringWriter(sb))
    {
        this.serializer.Serialize(writer, this);
    }

    return sb.ToString();
}
您无缘无故地创建了一个额外的
内存流


但是,如果您正在将字符串写入文件,那么为什么不将
FileStream
发送到
Serialize()
方法?

看起来您的方法可以清理为:

public virtual string Serialize()
{
    StringBuilder sb = new StringBuilder();
    using (StringWriter writer = new StringWriter(sb))
    {
        this.serializer.Serialize(writer, this);
    }

    return sb.ToString();
}
您无缘无故地创建了一个额外的
内存流


但是,如果您正在将字符串写入文件,那么为什么不向
Serialize()
方法发送一个
FileStream

一些代码片段会很有帮助……尝试使用StringBuilder并重用它,同时,如果有那么多记录,也许将它们保存在文件系统/DB上会很有效,我同意,但我在一家大公司工作,不能发布专有代码。K伊万诺夫——我会试试StringBuilder。至于记录的数量,我已经在序列化每个记录后将其写入fs。您分配了大的内容吗?我认为LOH碎片化可能是一个问题-一些代码片段会很有帮助…尝试使用StringBuilder并重用它,还有许多记录可能保存在文件系统/DB上会很有效我同意,但我为一家大公司工作,不能发布专有代码。K Ivanov--我会尝试使用StringBuilder。至于记录的数量,我已经在序列化每个记录后将其写入fs。您分配了大的内容吗?我认为LOH碎片化可能是一个问题-