【问题标题】:XmlDoc throws the process cannot access the file from tome to time?XmlDoc 有时会抛出进程无法访问文件?
【发布时间】:2015-05-13 09:43:24
【问题描述】:

我有以下代码用于编写基于数据合同的 XML 文件

public static void LogDataContractToFile(string XMLStringToLog, string filePathAndName)
        {
            //String documentPath = string.Empty;
            String xmlObject = string.Empty;

            FileInfo fileinfo;

            XmlDocumentFragment xmlDocumentFragment;
            XmlTextWriter xmlWriter;
            XmlDocument xmlDocument = null;

            lock (LogDataContractToFileLock)
            {

                filePathAndName = filePathAndName.ToLower();

                while (_workingWithFile.Contains(filePathAndName))
                    Thread.Sleep(1000);

                _workingWithFile.Add(filePathAndName.ToLower());

                try
                {

                    #region Create XMLFile
                    fileinfo = new FileInfo(filePathAndName);

                    if (!fileinfo.Exists)
                    {
                        DirectoryInfo info = new DirectoryInfo(fileinfo.DirectoryName);
                        if (info.Exists == false)
                            info.Create();

                        using (xmlWriter = new XmlTextWriter(filePathAndName, System.Text.Encoding.UTF8))
                        {
                            xmlWriter.Formatting = Formatting.Indented;
                            xmlWriter.WriteStartDocument();
                            xmlWriter.WriteStartElement("root");
                            xmlWriter.WriteStartElement("objects");
                            xmlWriter.WriteEndElement();
                            xmlWriter.WriteEndElement();
                            xmlWriter.WriteEndDocument();
                            xmlWriter.Close();
                        }
                    }
                    else
                    {
                        //Se så att filen är 50 MB eller mindre
                        while (fileinfo.Length > 52428800)
                        {
                            xmlDocument = new XmlDocument();
                            xmlDocument.Load(filePathAndName);

                            xmlDocument.RemoveChild(xmlDocument.LastChild);
                            xmlDocument.Save(filePathAndName);
                            xmlDocument = null;
                        }
                    }
                    #endregion

                    xmlObject = XMLStringToLog;

                    //Open document
                    xmlDocument = new XmlDocument();
                    xmlDocument.Load(filePathAndName);

                    //Create a new fragment in current document
                    xmlDocumentFragment = xmlDocument.CreateDocumentFragment();
                    xmlDocumentFragment.InnerXml = xmlObject;

                    //Add new fragment after the first child
                    xmlDocument.DocumentElement.InsertBefore(xmlDocumentFragment, xmlDocument.DocumentElement.FirstChild);
                    xmlDocument.Save(filePathAndName);
                    xmlDocument = null;
                }
                finally
                {
                    _workingWithFile.Remove(filePathAndName.ToLower());
                }
            }
        }

问题是我时不时收到The process cannot access the file 异常? XmlDocument 没有任何处置,所以我不能使用 using。应该如何妥善处理?

请注意,我坚持使用 .NET 4.0。

【问题讨论】:

  • 无论_workingWithFile 是什么,它看起来都不是线程安全的。有可能两个线程看到它不包含相同的文件并都添加它。
  • 您的应用程序意外地尝试从多个线程访问同一个文件两次。您需要使用线程同步机制来防范这种情况。
  • 谢谢,我正在考虑这个问题,所以我加了一个锁。这不会锁定特定文件(不认为我需要那个)。锁定特定文件会很棒,但从我读到的内容来看,锁定字符串对象并不好?

标签: c# .net xml filestream xmldocument


【解决方案1】:

要安全地检查一个元素并在它不存在时添加它,您应该使用ConcurrentDictionary:

private readonly ConcurrentDictionary<string,bool> _workingWithFile = new ConcurrentDictionary<string,bool>();
public static void LogDataContractToFile(string XMLStringToLog, string filePathAndName)
{
    ...
    lock (LogDataContractToFileLock)
    {
        ...

        while(!_workingWithFile.TryAdd(filePathAndName, true))
        {
            Thread.Sleep(1000);
        }
        ...
        try
        {
            ...
        }
        finally
        {
            //Perhaps check the result here.
            bool result;
            _workingWithFile.TryRemove(filePathAndName, out result);
        }
    }
}

【讨论】:

  • 看起来不错,它是一种锁定,但锁定在特定的文件名(字符串)上。我会试试这个。
  • 好的,现在开始,我在 .NET 4.0 上备货
  • 它也在.NET 4.0 中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多