2016-10-27 172 views
3

我有一个Web服务产生随机错误,我想我找到了错误。处理并发读取/写入文件

基本上,它是读取一个配置文件,如下所示,然后装入一个如下:

var config = File.ReadAllText(filename); 
xmlDoc.Load(config); 

然而,在稍后的时间(可能是第二版本)的配置值中的一个被更新和文件保存

xmlDoc.Save(filename); 

所以,现在我遇到了更多的错误(不幸的是,原开发商增加了一个空try块,所以我不能检查刚才)第一次读操作过程中,我认为这是因为它试图读取文件就像从IIS产生的另一个进程在.Save中一样一部分。我不知道File.ReadAllText是如何工作的以及它是否会在写入锁定文件时失败。

什么是解决这个问题的最佳解决方案,以确保阅读始终有效?正在写入的值只是一个计数器,如果失败,它将被忽略,因为它并不重要,但宁愿写入它。我想我可以把它放到一个单独的配置文件中,并与错误一起生活,但我宁愿它只是一个文件。

谢谢。

+0

对一个静态对象使用lock()以确保只有一个线程可以同时访问该文件。 – Gusman

+0

谢谢。这是否是在我的IIS Web服务中执行它的标准方式,假设许多进程想要同时连续读取和写入?顺便说一句,我是否正确地写了锁定读取? –

+0

@gusman OP认为读取来自不同的进程而不是不同的线程,所以它需要一个互斥锁而不是锁 –

回答

2

您可以使用锁,以确保读取被写入和副沃瑟前完成。如:

using System; 
using System.Threading; 

class Program 
{ 
    static readonly object _fileAccess = new object(); 

    static void Write() 
    { 
     // Obtain lock and write 
     lock (_fileAccess) 
     { 
      // Write data to filename 
      xmlDoc.Save(filename); 
     } 
    } 

    static void Read() 
    { 
     // Obtain lock and read 
     lock (_fileAccess) 
     { 
      // Read some data from filename 
      xmlDoc.load(filename); 
     } 
    } 

    static void Main() 
    {  
     ThreadStart writeT = new ThreadStart(Write); 
     new Thread(writeT).Start(); 

     ThreadStart readT = new ThreadStart(Read); 
     new Thread(readT).Start(); 
    } 
} 

使用锁,Read()必须等待Write()完成并且Write()必须等待Read()完成。

+0

谢谢。所以我不需要将我的配置分开为只读和可写元素,因为我正在考虑这样做。此外,我认为这将跨越多个线程IIS应用程序池可能正在为同时请求创建,无论我在代码中读取或写入我的配置我使用线程启动而不是简单地调用它? –

+0

是的,你不需要把它们分开。并且锁定通过设计是线程安全的,也注意到锁定的对象是静态的,所以在应用程序生命周期中只有一个实例会存在。线程启动也会 –

0

要获得关于如何File.ReadAllText()作品,望着源,它采用了StreamReader内部又使用开了一个FileStreamFileAccess.ReadFileShare.Read问题,这样就会防止写入文件中的任何其它工艺(例如,您的XmlDocument.Save()),直到完成ReadAllText

同时,您XmlDocument.Save()最终使用FileStream打开与 FileAccess.WriteFileShare.Read,所以它将使File.ReadAllText()只要SaveReadAllText之前启动。

参考文献:https://referencesource.microsoft.com/#mscorlib/system/io/streamreader.cs,a820588d8233a829

https://referencesource.microsoft.com/#System.Xml/System/Xml/Dom/XmlDocument.cs,1db4dba15523d588

+0

感谢您抽出时间。所以也许我在错误的地方寻找使用你的链接我看到XmlWriter有一个FileShare。阅读相同的阅读器,因此它不应该失败。这就是代码指向我的位置:( –

+0

它们都具有'FileShare.Read',但是'XmlDocument.Save()'具有'FileAccess.Write',所以如果在'ReadAllText'仍在执行时尝试打开它会失败,所以很多写/读/文件访问/文件共享 - 这有点令人困惑:o) –