2010-01-13 6 views
3

J'essaie d'enregistrer un XDcoument sur une clé USB qui n'a pas assez d'espace mémoire disponible. (Ceci est une condition de test spéciale pour l'application) Bien que l'application donne une exception comme ci-dessous, je ne peux pas l'obtenir dans le bloc try catch autour du XDocument.Save (filePath). On dirait que c'est un lancer retardé. Est-ce un problème LINQ ou est-ce que je fais quelque chose de mal?Exception de mémoire pendant XDocument.Save()

alt text http://img211.imageshack.us/img211/8324/exce.png

System.IO.IOException was unhandled 
Message="There is not enough space on the disk.\r\n" 
Source="mscorlib" 
StackTrace: 
    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) 
    at System.IO.FileStream.WriteCore(Byte[] buffer, Int32 offset, Int32 count) 
    at System.IO.FileStream.FlushWrite(Boolean calledFromFinalizer) 
    at System.IO.FileStream.Dispose(Boolean disposing) 
    at System.IO.FileStream.Finalize() 

Répondre

5

Vous avez trouvé un bug dans le framework. XDocument.Save (chaîne) utilise l'instruction "using" pour s'assurer que le flux de sortie est éliminé. Cela dépend de l'encodage que vous avez utilisé dans l'instruction de traitement, mais le System.Xml.XmlUtf8RawTextReader interne serait un outil commun pour implémenter le rédacteur de texte. Le bug: le programmeur Microsoft qui a écrit cette classe a oublié d'implémenter la méthode Dispose(). Seule la méthode Close() est implémentée.

Il est plutôt étrange que ce bogue n'ait pas encore été signalé sur le site de commentaires connect.microsoft.com. Cela devrait causer des problèmes en général parce que le fichier reste ouvert jusqu'à ce que le thread finalizer s'exécute. Bien que cela ne prenne normalement pas beaucoup de temps, quelques secondes. Sauf dans votre cas où vous quittez le programme juste après avoir écrit et avez la malchance de manquer d'espace disque au moment exact où le tampon est vidé.

Une solution de contournement pour ce bogue consiste à utiliser à la place la surcharge XDocument.Save (TextWriter), en passant un StreamWriter dont l'encodage correspond à l'encodage du XML.

+0

Hey merci pour la réponse. Dans mon cas, je suis délibérément fait que mon pouce commande moins d'espace que ce dont j'ai besoin. C'est une condition de test que je vérifie. –

+1

Eh bien, un autre effet secondaire du bug est que vous ne seriez pas en mesure d'éjecter votre clé USB. –

1

regard sur la trace de pile. Cette trace commence par un appel Finalize, qui effectue un Dispose, qui effectue un FlushWrite, qui appelle WriteCore, qui reçoit l'erreur.

En d'autres termes, videz d'abord vos données.

Postez le code que vous utilisez pour écrire et nous pouvons vous montrer où faire le flush.

0

fureter dans le réflecteur, les dernières lignes sont

using (XmlWriter writer = XmlWriter.Create(fileName, xmlWriterSettings)) 
{ 
    this.Save(writer); 
} 

Cela signifie, l'exception est levée lorsque l'écrivain est disposé.
Je suppose, il vaudra mieux vérifier l'espace disque disponible avant d'appeler Save.

EDIT: Avez-vous Dispose d tout objet dont l'instance de XDocument dépendait avant de passer un appel à Save?

+0

Les dernières lignes de quoi? En outre, cela n'est pas compatible avec la trace de la pile. Il n'y aurait pas de méthode Finalize sur la pile. –

+1

La vérification de l'espace disque ne vous sauvera pas si un autre processus utilise l'espace disque que vous alliez utiliser pour votre processus après avoir effectué la vérification. –

+0

@Erik: Il pourrait y avoir plusieurs scénarios, si l'on doit rendre les choses infaillibles :) L'OP peut voir si le scénario que vous avez décrit est un cas valide ou non. – shahkalpesh

0

XDocument.Save(string) n'a pas de bogue, il met en œuvre la méthode Dispose. L'instruction à l'aide est: - (comme décrit également ci-dessus)

utilisant (XmlWriter writer = XmlWriter.Create(fileName, xmlWriterSettings)) this.Save(writer);

Et XmlWriter a un Dispose(), il implémenter l'interface IDisposable.

Questions connexes