Вызов OutOfMemoryError XmlSerializer. Десериализуйте () - не связанный с размером XML!

Это - действительно сумасшедшая ошибка. Следующее бросает OutOfMemoryException, для отрывков XML, которые очень коротки и просты (например, ):

public static T DeserializeXmlNode(XmlNode node)
{
    try
    {
        return (T)new XmlSerializer(typeof(T))
            .Deserialize(new XmlNodeReader(node));
    }
    catch (Exception ex)
    {
        throw; // just for catching a breakpoint.
    }
}

Я читал в этой статье MSDN, что, если бы я использовал XmlSerializer с дополнительными параметрами в конструкторе, я закончил бы тем, что генерировал некэшируемые блоки сериализатора каждый раз, когда это назвали, вызвав Утечку блока. Но я не использую дополнительные параметры в конструкторе. Это также происходит на первом разе, когда это называют в недавно запущенном AppDomain, так, чтобы не имел смысла также.

Что дает?

8
задан Mike Atlas 17 May 2010 в 19:46
поделиться

3 ответа

На основании документации класса XmlSerializer вы должны кэшировать XmlSerializer, иначе это может вызвать снижение производительности или утечку памяти.

Hashtable serializers = new Hashtable();

// Use the constructor that takes a type and XmlRootAttribute.
XmlSerializer s = new XmlSerializer(typeof(MyClass), myRoot);

// Implement a method named GenerateKey that creates unique keys 
// for each instance of the XmlSerializer. The code should take 
// into account all parameters passed to the XmlSerializer 
// constructor.
object key = GenerateKey(typeof(MyClass), myRoot);

// Check the local cache for a matching serializer.
XmlSerializer ser = (XmlSerializer)serializers[key];
if (ser == null) 
{
    ser = new XmlSerializer(typeof(MyClass), myRoot);
    // Cache the serializer.
    serializers[key] = ser;
}
else
{
    // Use the serializer to serialize, or deserialize.
}
1
ответ дан 5 December 2019 в 20:14
поделиться

Вы не предоставили достаточно сведений, чтобы воссоздать проблему. Но читатель реализует IDisposable и от него следует утилизировать должным образом. Желательно обернуть его в блок using. Большинство разработчиков никогда не сталкиваются с проблемой, когда забывают избавиться от чего-либо, потому что сборщик мусора в конечном итоге уберет беспорядок. Однако нетрудно закодировать что-то, что вызывает проблемы, до того, как сборщик мусора приступит к очистке, или даже полностью предотвратит очистку.

public static T DeserializeXmlNode<T>(XmlNode node)
{
    XmlSerializer xs = new XmlSerializer(typeof(T));
    using(XmlNodeReader xr = new XmlNodeReader(node))
        return (T)xs.Deserialize(xr);
}
1
ответ дан 5 December 2019 в 20:14
поделиться

EDIT: Это не было решением, к сожалению, но это может помочь другим отследить очень похожую проблему. Этот ответ здесь является фактическим решением.

Я верю, что нашел решение этой проблемы. Это ошибка в .NET 3.5 SP1.

Serialization hangs or throws an OutOfMemoryException with static delegate and ISerializable on 3. 5 SP1 (ID: 361615):

Когда общий класс реализует ISerializable и имеет статический член делегата, который использует аргументы общего типа, двоичная десериализация зависает (на 32-битной системе с Windows Server 2003) или выбрасывает OutOfMemoryException (на 64-битной системе с Windows Server 2008).

Эта ошибка возникает в .NET 3.5 SP1 и не возникала в .NET 3.5 без SP1.

Решением является установка KB957543 горячего исправления.

2
ответ дан 5 December 2019 в 20:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: