我有一个从Windows服务调用的类库,可以同时多次调用类库。
我有一个问题,我必须在我的类中读取文件内容,所以我得到错误,如果该类被许多进程调用,该文件正被另一个进程使用。
这是我阅读文件内容的方式:
File.ReadAllBytes("path");
在这种情况下,最佳解决方案是什么?
谢谢
答案 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.Read
和FileShare.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如何使用Mutex
和Semaphor
类型实现一个。
解决方案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
}