Мое веб-приложение возвращает файл из файловой системы. Эти файлы являются динамическими, поэтому я не могу узнать их имена и сколько их будет. Если этот файл не существует, приложение создает его из базы данных. Я хочу избежать того, чтобы два разных потока воссоздавали один и тот же файл одновременно или чтобы поток пытался вернуть файл, пока другой поток его создает.
Кроме того, я не хочу блокировать элемент, общий для всех файлов. Поэтому я должен заблокировать файл только тогда, когда я его создаю.
Поэтому я хочу заблокировать файл до тех пор, пока его воссоздание не будет завершено, если другой поток попытается получить к нему доступ... ему придется подождать, пока файл будет разблокирован.
Я читал о FileStream.Lock, но мне нужно знать длину файла, и это не помешает тому, чтобы другой поток попытался прочитать файл, поэтому это не работает для моего конкретного случая.
Я также читал о FileShare.None, но он выдаст исключение (какой тип исключения?), если другой поток/процесс попытается получить доступ к файлу... поэтому я должен разработать "повторить попытку, пока происходит сбой", потому что я хотелось бы избежать генерации исключений... и мне не очень нравится такой подход, хотя, может быть, и нет лучшего способа.
Подход с FileShare.None будет примерно таким:
static void Main(string[] args)
{
new Thread(new ThreadStart(WriteFile)).Start();
Thread.Sleep(1000);
new Thread(new ThreadStart(ReadFile)).Start();
Console.ReadKey(true);
}
static void WriteFile()
{
using (FileStream fs = new FileStream("lala.txt", FileMode.Create, FileAccess.Write, FileShare.None))
using (StreamWriter sw = new StreamWriter(fs))
{
Thread.Sleep(3000);
sw.WriteLine("trolololoooooooooo lolololo");
}
}
static void ReadFile()
{
Boolean readed = false;
Int32 maxTries = 5;
while (!readed && maxTries > 0)
{
try
{
Console.WriteLine("Reading...");
using (FileStream fs = new FileStream("lala.txt", FileMode.Open, FileAccess.Read, FileShare.Read))
using (StreamReader sr = new StreamReader(fs))
{
while (!sr.EndOfStream)
Console.WriteLine(sr.ReadToEnd());
}
readed = true;
Console.WriteLine("Readed");
}
catch (IOException)
{
Console.WriteLine("Fail: " + maxTries.ToString());
maxTries--;
Thread.Sleep(1000);
}
}
}
Но мне не нравится, что приходится ловить исключения, пробовать несколько раз и ждать неточное количество времени :|