任何人都可以告诉我们下面这段代码有什么问题吗? 我们这里有一个对象序列化程序,它应该返回传递给它的任何对象的XML字符串。
我们一直在讨论这个问题,因为我们有一个程序可以多次调用这个程序,我们看到我们的内存使用量很高(甚至在程序完成后仍然存在)...我们已经完成了搜索但无济于事。 stream对象在一个“using”语句中,所以我们认为这应该是自己处理的..请帮忙。
public static string ToXML(this IMessage m)
{
try
{
var serializer = SerializerFactory.Create(m.GetType());
using (var stream = new MemoryStream())
{
serializer.Serialize(new[] { m }, stream);
stream.Position = 0;
var s = Encoding.ASCII.GetString(stream.ToArray());
return s;
}
}
catch (Exception e)
{
return string.Format("Message unserializable: {0}", e.Message);
}
}
btw SerializerFactory如下所示:
public class SerializerFactory
{
public static IMessageSerializer Create(Type t)
{
var types = new List<Type> { t };
var mapper = new MessageMapper();
mapper.Initialize(types);
var serializer = new XmlMessageSerializer(mapper);
serializer.Initialize(types);
return serializer;
}
}
答案 0 :(得分:6)
该代码没有任何错误错误;请注意using
基本上是MemoryStream
上的无操作,因为它只有托管资源,托管资源是其中的域GC; GC没有太大的担心,直到它感觉收集一些内存,所以我不会过分强调 - 或者:如果有问题,可能不是这个。
但有一点是,您可以在编码步骤中避免使用缓冲区:
var s = Encoding.ASCII.GetString(stream.GetBuffer(), 0, (int)stream.Length);
实际上,我很想在默认情况下使用UTF8,而不是ASCII。
最后一个想法:你的SerializerFactory
本身做了泄漏的事情吗?例如,您是否通过任何更复杂的构造函数创建new XmlSerializer(...)
?最简单的形式:
new XmlSerializer(typeof(SomeType));
正常 - 它在内部缓存每个类型的内部/实际序列化程序,并对以这种方式创建的每个XmlSerializer
实例重新使用它。但是,对于更复杂的构造函数重载,它 not 执行此缓存:它每次都会创建并加载新的动态程序集。以这种方式加载的程序集 永远不会被卸载 - 所以是的, 会导致内存泄漏。我非常希望看到如何创建序列化程序实例,以查看 是否是实际问题。请注意,通过在工厂中创建自己的序列化程序缓存,这些情况通常很容易解决:
public class SerializerFactory
{
// hashtable has better threading semantics than dictionary, honest!
private static readonly Hashtable cache = new Hashtable();
public static IMessageSerializer Create(Type t)
{
var found = (IMessageSerializer)cache[t];
if(found != null) return found;
lock(cache)
{ // double-checked
found = (IMessageSerializer)cache[t];
if(found != null) return found;
var types = new List<Type> { t };
var mapper = new MessageMapper();
mapper.Initialize(types);
var serializer = new XmlMessageSerializer(mapper);
serializer.Initialize(types);
cache[t] = serializer;
return serializer;
}
}
}
答案 1 :(得分:3)
MemoryStream
上没有发生内存泄漏,它实际发生在XmlSerializer
:
“XmlSerializer构造函数的这个重载不会缓存动态生成的程序集,但每次实例化一个新的XmlSerializer时都会生成一个新的临时程序集!该应用程序以临时程序集的形式泄漏非托管内存。“
看一下这篇文章:
http://msdn.microsoft.com/en-us/magazine/cc163491.aspx
不是每次都创建XmlSerializer
,而是需要为每种类型缓存,以解决您的问题。