【问题标题】:XML Re-deserialization ErrorXML 重新反序列化错误
【发布时间】:2014-02-27 23:37:06
【问题描述】:

我的应用程序在打开时从 XML 文件中反序列化数据。应用程序第一次加载时反序列化工作正常,但是当我尝试重新打开程序时,出现以下错误:

2/27/2014 6:27:30 PM  : Error: There is an error in XML document (9, 6).. Stacktrace:    at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events) at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle) at XMLInterface.XMLInterface.Deserialize(String CallingSub, String LocalFileURI) in C:\AzTech\Satellite\Code Repository\trunk\Ribbon\XMLInterface\Code\XMLInterface.vb:line 66

此外,应用程序是加载项解决方案的一部分,因此当应用程序关闭时,加载项仍在运行。如果我关闭加载项并重新运行它,序列化工作正常;只有在我自行关闭并重新打开应用程序后才会发生错误。

这是我的代码:

        Dim ser As New XmlSerializer(ElementsLocal.GetType)
        Dim objStreamReader As New StreamReader(LocalFileURI)
        ElementsLocal = ser.Deserialize(objStreamReader)
        objStreamReader.Close()
        objStreamReader.Dispose()
        ser = Nothing
        GC.Collect()

有人有什么想法吗?我需要以某种方式释放文件吗?我假设一旦反序列化子退出,文件就会被释放,但不是这样吗?

编辑: 这些进程也会访问该文件(不确定这是否会影响这种情况):

    For Each Name As String In System.IO.Directory.GetFiles(My.Settings.savePath)
        Dim cBox As New ComboBoxItem
        cBox.Content = System.IO.Path.GetFileNameWithoutExtension(Name)
        cBox.Style = TryFindResource("blackComboBoxItem")
        cmbBxQBDNames.Items.Add(cBox)
    Next

编辑 2: 按照建议包装代码也不起作用:

        Dim ser As New XmlSerializer(ElementsLocal.GetType)
        Using fs As FileStream = New FileStream(LocalFileURI, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
            Using objStreamReader As New StreamReader(fs)
                ElementsLocal = ser.Deserialize(objStreamReader)
            End Using
        End Using
        ser = Nothing

【问题讨论】:

  • 拥有整个错误会很有帮助,而不仅仅是堆栈跟踪。
  • 我之前把整个错误信息都放进去了,但是被别人删掉了。
  • 它看起来像是日志文件的堆栈跟踪转储。我指的是整个错误,它告诉您出了什么问题以及哪里出了问题(我们已经有了那部分)。
  • 我认为唯一缺少的是:“对象引用未设置为对象的实例。”
  • 这告诉我的不仅仅是堆栈跟踪。在不知道行号的情况下,我猜第 66 行是 Dim objStreamReader ... 行。如果是这种情况,您还没有初始化或设置 LocalFileURI 的值。知道哪些包含的代码行是哪些行号有助于调试。

标签: xml vb.net serialization


【解决方案1】:

问题在于,当您使用 StreamReader 打开文件时,它会锁定该文件以防被其他进程使用。这包括当您启动第二个实例并且第一个实例没有完全耗尽内存时的应用程序。试试这个代码:

Dim ser As New XmlSerializer(ElementsLocal.GetType)
Using fs As FileStream = New FileStream(LocalFileURI, _
                                        FileMode.Open, _
                                        FileAccess.Read, _
                                        FileShare.ReadWrite)
    Using objStreamReader As New StreamReader(fs)
        ElementsLocal = ser.Deserialize(objStreamReader)
    End Using
End Using
ser = Nothing
GC.Collect()

Using 语句定义了一个你想要清理干净的对象。在End Using 行,编译器将Dispose 您在Using 行中创建的对象(这也会为您关闭它)。当您处理文件、网络流或其他真正应该一次只处理一件事的事物时,Using 语句是一个不错的选择。

FileStream 对象为您提供了一种打开具有不同访问级别的文件的方法,以最小化(或最大化)对其他进程的干扰。您只想打开现有文件,而不是创建或附加 - FileMode。你不需要对这个文件做任何事情,除了阅读它的内容 - FileAccess。您希望尽量减少可能需要访问该文件的其他进程的问题 - FileShare

【讨论】:

  • 这个解决方案看起来很有希望,但它没有修复错误 - 我仍然收到“对象引用...”消息。
  • 代码的其他部分是否打开了同一个文件?如果是这样,您将需要执行类似的操作来防止文件锁定问题。
  • 我发现的唯一一个以某种方式访问​​文件的其他代码,我已添加为编辑。这些过程会影响这种情况吗?
  • 如果你像上面那样使用StreamReader打开文件,肯定可以。
  • 仍然没有运气 - 我用为组合框项目提供硬编码名称的代码替换了调用文件的代码。
猜你喜欢
  • 2014-03-13
  • 1970-01-01
  • 1970-01-01
  • 2018-06-04
  • 2011-08-09
  • 2010-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多