【问题标题】:What's the best way to synchronize XmlWriter access to a file to prevent IOExceptions?将 XmlWriter 访问同步到文件以防止 IOExceptions 的最佳方法是什么?
【发布时间】:2010-10-01 07:56:46
【问题描述】:

在同一个文件上调用 XmlWriter.Create 的应用程序中有多个地方,都通过以下函数访问。当一个人打电话而另一个人还在写信时,我得到一个 IOException。锁定或同步访问的最佳方式是什么?

这是正在使用的函数:

        public void SaveToDisk()
    {
        try
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            using (XmlWriter writer = XmlWriter.Create(SaveFileAbsolutePath, settings))
            {
                XamlWriter.Save(this, writer);
                writer.Close();
            }

        }
        catch (Exception ex)
        {
            // Log the error
            System.Diagnostics.Debug.WriteLine(ex.Message);

            // Rethrow so we know about the error
            throw;
        }
    }

更新:看起来问题不仅来自对该函数的调用,还因为另一个线程正在读取该文件,而该函数正在写入。什么是最好的锁定方式,这样我们就不会在读取文件时尝试写入文件?

【问题讨论】:

    标签: c# file-io ioexception xmlwriter


    【解决方案1】:

    使用锁可以解决你的并发问题,从而避免 IOException,但是你必须记住在 SaveToDisk 和 ReadFromDisk 上使用相同的对象(我假设这是读取函数),否则只有当你锁定时它是完全没用的阅读。

    private static readonly object syncLock = new object();
    
    public void SaveToDisk()
    {
         lock(syncLock)
         {
              ... write code ...
         }
    }
    
    public void ReadFromDisk()
    {
         lock(syncLock)
         {
              ... read code ...
         }
    }
    

    【讨论】:

      【解决方案2】:

      静态锁应该快速简单地完成这项工作:

      private static readonly object syncLock = new object();
      

      那么……

      public void SaveToDisk()
      {
          lock(syncLock)
          {
              ...your code...
          }
      }
      

      您也可以使用[MethodImpl(MethodImplOptions.Synchronized)](在接受实例作为参数的静态方法上 - 例如,扩展方法),但显式锁更通用。

      【讨论】:

        【解决方案3】:

        我实际上会使用ReaderWriterLock 来最大化并发性。您可以允许多个阅读器,但一次只能允许一个作者。

        private ReaderWriterLock myLock = new ReaderWriterLock();
        
        public void SaveToDisk()
        {
             myLock.AcquireWriterLock();
             try
             {
                  ... write code ...
             } 
             finally
             {
                  myLock.ReleaseWriterLock();
             }
        }
        
        public void ReadFromDisk()
        {
             myLock.AcquireReaderLock();
             try
             {
                  ... read code ...
             } 
             finally
             {
                  myLock.ReleaseReaderLock();
             }
        }
        

        只需确保使用FileShare.Read 打开文件,以便后续读取不会失败。

        【讨论】:

          猜你喜欢
          • 2012-11-30
          • 1970-01-01
          • 2012-09-11
          • 2013-03-25
          • 2016-12-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多