同时从多个进程读取文件内容

时间:2015-08-26 07:17:48

标签: c#

我有一个从Windows服务调用的类库,可以同时多次调用类库。

我有一个问题,我必须在我的类中读取文件内容,所以我得到错误,如果该类被许多进程调用,该文件正被另一个进程使用。

这是我阅读文件内容的方式:

  File.ReadAllBytes("path");

在这种情况下,最佳解决方案是什么?

谢谢

2 个答案:

答案 0 :(得分:1)

以下代码演示了如何通过设置其共享权限来访问文件。第一个using块创建并写入文件,第二个和第三个using块访问并读取文件。

var fileName = "test.txt";
using (var fsWrite = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
{
    var content = Encoding.UTF8.GetBytes("test");

    fsWrite.Write(content, 0, content.Length);
    fsWrite.Flush();

    using (var fsRead_1 = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    {
        var bufRead_1 = new byte[fsRead_1.Length];
        fsRead_1.Read(bufRead_1, 0, bufRead_1.Length);
        Console.WriteLine("fsRead_1:" + Encoding.UTF8.GetString(bufRead_1));

        using (var fsRead_2 = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        {
            var bufRead_2 = new byte[fsRead_2.Length];
            fsRead_2.Read(bufRead_2, 0, bufRead_2.Length);
            Console.WriteLine("fsRead_2:" + Encoding.UTF8.GetString(bufRead_2));
        }
    }
}

答案 1 :(得分:1)

使用Mutex在不同进程之间进行同步。 File.ReadAllBytes在读取文件时使用FileAccess.ReadFileShare.Read,因此通常您不需要在此处使用任何锁定。所以你得到这个例外是因为文件正在某处(或者至少被锁定以便写入)。

解决方案1 ​​ - 如果您是撰写此文件的人

private static Mutex mutex;

public void WriteFile(string path)
{
    Mutex mutex = GetOrCreateMutex();
    try
    {
        mutex.WaitOne();
        // TODO: ... write file
    }
    finally
    {
        mutex.ReleaseMutex();
    }
}

public byte[] ReadFile(string path)
{
    // Note: If you just read the file, this lock is completely unnecessary
    // because ReadAllFile uses Read access. This just protects the file
    // being read and written at the same time
    Mutex mutex = GetOrCreateMutex();
    try
    {
        mutex.WaitOne();
        return File.ReadAllBytes(path);
    }
    finally
    {
        mutex.ReleaseMutex();
    }
}

private static Mutex GetOrCreateMutex()
{
    try
    {
        mutex = Mutex.OpenExisting("MyMutex");
    }
    catch (WaitHandleCannotBeOpenedException)
    {
        mutex = new Mutex(false, "MyMutex");
    }
}

备注:此处ReadWriteLock会更好,因为您可以在未写入文件时安全地并行读取文件;但是,.NET中没有内置的进程间读写锁。 Here is an example如何使用MutexSemaphor类型实现一个。

解决方案2 - 如果您只是阅读文件

您必须准备好在第三个进程写入文件时锁定该文件:

public byte[] TryReadFile(string path, int maxTry)
{
    Exception e;

    for (int i = 0; i < maxTry; i++)
    {
        try
        {
            return File.ReadAllBytes(path);
        }
        catch (IOException io)
        {
            e = io;
            Thread.Sleep(100);
        }
    }

    throw e; // or just return null
}