XDocument.Save() 某物块文件

XDocument.Save() something blocks file

我打算使用 XDocument.Load() 加载一个 xml 文件,更新一些元素的值,然后使用 XDocument.Save() 保存它。读取正常,保存不行。

我的代码:

    class XmlDocHandler
{
    private string filePath;
    private XDocument xmlDoc;
    private IList<XElement> updatedElements;

    public IEnumerable<XElement> Elements => xmlDoc.Descendants();
    public IEnumerable<XElement> UpdatedElements => updatedElements;

    public XmlDocHandler(string filePath)
    {
        this.filePath = filePath;
        ReloadFromFile();
        updatedElements = new List<XElement>();
    }

    public void UpdateElements(IEnumerable<XElement> newElements)
    {
        updatedElements = new List<XElement>();
        foreach (XElement newElement in newElements)
        {
            XElement element = xmlDoc.Descendants()
                                     .FirstOrDefault(x => x.Name.LocalName == newElement.Name.LocalName);
            if (element != null)
            {
                if (element.Value != newElement.Value)
                {
                    element.Value = newElement.Value;
                    updatedElements.Add(element);
                }
            }
        }
    }

    public void ReloadFromFile()
    {
        bool success = false;

        if (File.Exists(filePath))
        {
            try
            {
                xmlDoc = XDocument.Load(filePath);

                success = true;
            }
            catch
            {

            }
        }

        if (!success)
        {
            xmlDoc = new XDocument();
        }
    }

    public void WriteToFile()
    {
        xmlDoc.Save(filePath);
    }
}

据我所知,它是一组序列化的操作,没有并行或其他花哨的东西,可能会阻塞我的文件。我没有发现 XDocument.Load("c:\file.xml") 会在文件上创建锁的迹象。

我已经尝试替换直接操作

xmlDoc = XDocument.Load(filePath);

xmlDoc.Save(filePath);

使用此处找到的基于流的方法: XDocument.Save() unable to access file 和这里 c# xml.Load() locking file on disk causing errors 这样它们看起来像这样:

正在加载..

using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
    xmlDoc = XDocument.Load(fs);
}

using (var sr = new StreamReader(filePath))
{
    xmlDoc = XDocument.Load(sr);
}

和写作..

using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Write, FileShare.Write))
{
    xmlDoc.Save(fs);
}

无论我做什么,正确关闭流并确保文件未在任何编辑器中打开或以其他方式使用,愚蠢的文件始终是 "used by another process"。

我在这里到底没有看到什么?有问题的文件位于我的 .exe 文件旁边的 VS2017 Pro 调试输出文件夹中。我不知道我对该文件夹的写入权限有限。

尝试

fs.Flush();

也许

fs.Close();

写完之后。据我所知,IO 流中正在进行某种缓存。可能会有帮助。

此致。

我发现了导致这次失败的错误!

此问题的原因与 XDocument.Load().Save() 无关。在为解决我的问题而松了一口气的同时,我也很尴尬地承认我多年前自己的一个实现导致了这个问题。

我曾经为 System.Windows.Forms.OpenFileDialog() 制作了一个包装器 class,这将简化我经常使用的 OFD class 配置。在其中我使用了类似

的东西
var ofd = new OpenFileDialog();
try
{
    if((var stream = ofd.OpenFile()) != null)
    {
        return ofd.FileName;
    }
    else
    {
        return "file already opened";
    }
}
catch
{
    return "error";
}

同时将 ofdstream 引用保留为实例变量。现在看这段代码让我不寒而栗(或笑),但那时候我不知道更好。当然,这现在让我很痛苦,因为我没有关闭那个流!我几年前犯下的罪行现在让我花了将近 2 天的工作时间。

我的补救措施:我重写了我的 OFD 包装器 class 以使用 Microsoft.Win32.OpenFileDialog class,因为它似乎没有任何基于流的东西会无意中锁定文件.

经验教训(以及我热烈推荐给其他人的内容):在使用流或其他可以保持打开状态并导致内存泄漏的构造时,永远不要相信自己。阅读通过调用通常负责此类清理工作的 IDisposable.Dispose() 方法来使用处置模式的 using 块语句。最后,使用 VS 中简洁的分析功能,这些功能在我制作 OFD 包装器时不可用,它们有助于发现此类问题。

感谢所有提供帮助的人,也感谢提供他们帮助的人。