在 C# 中保存 XML 流表示它正在被另一个进程使用

Posted

技术标签:

【中文标题】在 C# 中保存 XML 流表示它正在被另一个进程使用【英文标题】:Saving XML stream in C# says that it's being used by another process 【发布时间】:2009-05-11 19:07:09 【问题描述】:

我有this 开源库,我在解决问题时遇到了一些麻烦...这个库允许轻松创建一个 XML 文件来存储应用程序设置。但我在保存更改时遇到了问题。

我有另一个应用程序正在使用这个库,每次应用程序窗口调整大小时,我都会调用库的 Save() 方法将窗口大小/位置保存到 XML 文件中。

大多数时候它工作正常,一切都被保存了。不过,有时我会收到一个异常,说该文件正在被另一个进程使用。

我确实需要确保每次调用 Save() 方法时都保存更改,我需要以某种方式处理此异常或防止其发生。

你们对最好的处理这种情况有什么建议?

Save() 方法的代码如下:

public void Save() 
    // Create a new XML file if there's no root element
    if(xDocument.DocumentElement == null) 
        xDocument = new XmlDocument();
        xDocument.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
            "<" + XmlRootElement + ">\n</" + XmlRootElement + ">");
    

    // OMITTED CODE WAS HERE (NOT IMPORTANT FOR THE PROBLEM)

    // Create a new XML writer for the XML file
    XmlWriter xWriter = XmlWriter.Create(XmlFilePath, new XmlWriterSettings() 
        Indent = true,
        IndentChars = "\t"
    );

    // Sort the XML file using the XSL sylesheet and save it
    xslTransform.Transform(xDocument, xWriter);

    // Clear the buffer and close the XML writer stream
    xWriter.Flush();
    xWriter.Close();

【问题讨论】:

我看到您接受了将 lock 语句放入的答案,这很酷,但我会提醒您仍然在代码中使用 using 语句。它将确保您始终按预期清理资源。如果您遇到异常,您将无法正确关闭文件,并且可能仍然存在文件争用,因为锁定无济于事。 我也在用,谢谢关心。我接受了这个答案,因为它解决了这个问题的问题。我不再有我曾经有过的例外,也没有任何不同的例外(不是说我将来不会有),所以问题得到了解决。不过,您的附加信息很好,这就是我投票支持“有用的答案”的原因:) 【参考方案1】:

XmlWriter 是 IDisposable。您应该将其包装在 using() 子句中。 http://msdn.microsoft.com/en-us/library/system.xml.xmlwriter.aspx

【讨论】:

你能解释一下为什么你几乎可以肯定我应该使用 using() 而不是 lock() 吗?到目前为止,我了解锁定的原因,我认为这是有道理的,但不是为了使用...... 哎呀;我可能说错了。 using() 子句对于实现 IDisposable 的类是必不可少的。根据您的调整大小逻辑是否允许交错或并发调整大小事件,锁定也可能是必要的。【参考方案2】:

我必须结合这里已经给出的答案。

出于多种原因,您的 XmlWriter 应该位于 using 块中。您应该处置它,以便尽快释放您的资源。此外,如果您在与它交互时抛出异常怎么办。该文件不会被正确关闭,至少在终结器启动并释放您的资源之前。

即使使用 using 语句,您也“可能”对文件有争用,需要将 Save 代码放在 lock 语句中。该方法本质上是不可重入的,因为文件是共享资源。如果您没有多个线程,那么在它周围加锁可能会过度杀戮,但您会确保正确控制对文件的访问。

要考虑的另一件事是,您可能希望将保存操作移至后台线程以将文件写出。如果你得到一个大的设置文件,你可能会导致奇怪的 UI 交互,因为每次用户调整大小时你都在等待文件写入,这发生在 UI 线程上。如果你这样做了,你肯定需要锁定对文件资源的访问。

【讨论】:

【参考方案3】:

可能是 window-resizing-completed 事件触发得如此之快,以至于调用了 save 函数,在它第一次完成运行之前再次调用。这将导致您描述的错误(使用该文件的另一个进程是......你!)。 Try surrounding your code with a lock, thusly:

lock(some_shared_object)

    //Your code here

【讨论】:

【参考方案4】:

您也可以尝试使用锁定语句。可能是这些方法相互超越。

【讨论】:

99.44% 确定它是 using() 语句。你不需要锁。 我不确定 using() 是根本问题,因为他调用了 XmlWriter.Close()。我没有看到一个 catch 块吞噬异常,所以我看不到他会错过任何飞出那里的异常,这是无论如何都不会调用 Close() 的唯一方法。

以上是关于在 C# 中保存 XML 流表示它正在被另一个进程使用的主要内容,如果未能解决你的问题,请参考以下文章

进程无法访问图像文件,因为它正被另一个进程使用

xmlDocument 已被另一个进程使用

System.IO.IOException: '该进程无法访问该文件,因为它正被另一个进程使用

运行 pub get 时出错:无法重命名目录,因为它正在被另一个进程使用

构建错误:“该进程无法访问该文件,因为它正在被另一个进程使用”

该进程无法访问该文件,因为它正被另一个进程 Streamwriter 使用