处理文件的并发读/写

时间:2016-10-27 21:12:48

标签: c# .net

我有一个产生随机错误的网络服务,我想我发现了这个错误。

基本上,它是按如下方式读取配置文件,然后加载到XmlDocument:

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

但是,稍后(可能是一秒钟之后)其中一个配置值会更新并保存文件

xmlDoc.Save(filename);

所以我现在遇到了更多错误(不幸的是原始开发人员在第一次READ操作中添加了一个空的try块,所以我现在无法检查),我认为这是因为它&# 39;尝试读取文件就像从IIS生成的另一个进程在.Save部分。我不知道File.ReadAllText如何工作以及它是否会在写锁定文件上失败。

处理此问题的最佳解决方案是什么,以确保阅读始终有效?正在写的值只是一个计数器,如果它失败则会被忽略,因为它不是那么重要但是更喜欢写的。我想我可以把它放到一个单独的配置文件中,然后查看错误,但我觉得它只是一个文件。

感谢。

2 个答案:

答案 0 :(得分:3)

您可以使用锁定来确保在写入和反之前完成读取。如:

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()完成。

答案 1 :(得分:0)

要回答关于File.ReadAllText()如何运作的问题,查看来源,它会在内部使用StreamReader,而FileStream会使用FileAccess.ReadFileShare.Read打开XmlDocument.Save() 1}},以便在ReadAllText完成之前阻止任何其他进程写入文件(例如您的XmlDocument.Save())。

与此同时,您的FileStream最终使用了FileAccess.Write FileShare.ReadFile.ReadAllText(),只要在Save之前ReadAllText开始,就会允许ID 123456789. 234567890.

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

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