Мое веб-приложение возвращает файл из файловой системы. Эти файлы являются динамическими, поэтому у меня нет возможности узнать имена, сколько их будет. Когда этот файл не существует, приложение создает его из базы данных. Я хочу избежать того, что два разных потока воссоздают один и тот же файл одновременно или что поток пытается вернуть файл, пока другой поток его создает.
Кроме того, я не хочу блокировать элемент, общий для всех файлов. Поэтому я должен заблокировать файл только тогда, когда я его создаю.
Итак, я хочу заблокировать файл до завершения его восстановления, если другой поток попытается получить к нему доступ ... ему придется ждать разблокировки файла.
Я читал о 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);
}
}
}
Но мне не нравится тот факт, что мне приходится ловить исключения, пробовать несколько раз и ждать неточное количество времени: |