Много процессов обрабатывают и записывают один файл
У меня есть txt файл ABC.txt, который будет прочитан и написан несколькими процессами. Поэтому, когда один процесс читает или записывает файл ABC.txt, файл ABC.txt должен быть заблокирован, чтобы другие процессы не могли читать или писать на него. Я знаю, что перечисление System.IO.FileShare может быть правильным способом справиться с этой проблемой. Но я использовал другой способ, который я не уверен, правильно ли это. Следующее - мое решение.
Я добавил в папку еще один файл Lock.txt. Прежде чем я смогу прочитать или записать в файл ABC.txt, я должен иметь возможность читать из файла Lock.txt. И после того, как я прочитал или написал файл ABC.txt, я должен освободить эту возможность. Ниже приведен код.
#region Enter the lock
FileStream lockFileStream = null;
bool lockEntered = false;
while (lockEntered == false)
{
try
{
lockFileStream = File.Open("Lock.txt", FileMode.Open, FileAccess.Read, FileShare.None);
lockEntered = true;
}
catch (Exception)
{
Thread.Sleep(500);
}
}
#endregion
#region Do the work
// Read from or write to File ABC.txt
// Read from or write to other files
#endregion
#region Release the lock
try
{
if (lockFileStream != null)
{
lockFileStream.Dispose();
}
}
catch
{
}
#endregion
На моем компьютере кажется, что это решение работает хорошо, но я все еще не могу убедиться, что он подходит.
Изменить: Много процессов, а не несколько потоков в одном процессе.
Ответы
Ответ 1
С# с именем EventWaitHandle - это путь сюда. Создайте экземпляр дескриптора ожидания в каждом процессе, который хочет использовать этот файл, и дайте ему имя, которое разделяется всеми этими процессами.
EventWaitHandle waitHandle = new EventWaitHandle(true, EventResetMode.AutoReset, "SHARED_BY_ALL_PROCESSES");
Затем при доступе к файлу подождите waitHandle
и по завершении обработки файла установите его так, чтобы следующий процесс в очереди мог получить к нему доступ.
waitHandle.WaitOne();
/* process file*/
waitHandle.Set();
Когда вы называете дескриптор ожидания события, это имя является общим для всех процессов в операционной системе. Поэтому, чтобы избежать возможности столкновений, используйте руководство для имени ( "SHARED_BY_ALL_PROCESSES" выше).
Ответ 2
Мьютекс в С# может использоваться для нескольких процессов. Вот пример для нескольких процессов, записывающих один файл:
using (var mutex = new Mutex(false, "Strand www.jakemdrew.com"))
{
mutex.WaitOne();
File.AppendAllText(outputFilePath,theFileText);
mutex.ReleaseMutex();
}
Вам нужно убедиться, что мьютексу присвоено уникальное имя, которое будет использоваться во всей системе.
Дополнительное чтение здесь:
http://www.albahari.com/threading/part2.aspx#_Mutex
Ответ 3
Ваше решение подвержено ошибкам. Вы в основном реализовали блокировку с двойной проверкой (http://en.wikipedia.org/wiki/Double-checked_locking), которая может быть очень опасной.
Лучшим решением было бы либо установить изоляцию потоков, когда только один поток когда-либо обращается к файлу и делает это, читая из очереди, по которой запросы на чтение или запись помещаются другими потоками (и, конечно, очередь защищена путем взаимного эксклюзивного доступа по потокам), или когда потоки синхронизируются либо с помощью устройств синхронизации (lock
разделы, так и без каких-либо изменений), либо с помощью какой-либо другой логики доступа к файлу (например, System.IO.FileShare
). )
Ответ 4
С# имеет встроенный lock
, и вы можете использовать его, создав статический объект, доступный для всех потоков:
private static object lockObject {get;set;}
public static object LockObject {get{return lockObject ?? lockObject = new object();}}
void YourMethod()
{
lock(LockObject) // all other threads will wait for y
{
using(var lockFileStream = File.Open("Lock.txt", FileMode.Open, FileAccess.Read, FileShare.None))
{
//Do what you need with the file.
}
}
}
Это создает подход Thread Threading к вашей проблеме.
Ответ 5
Если бы это был я, я бы установил что-то вроде SQL Server Compact Edition для чтения/записи этих данных.
Однако, если вы хотите иметь возможность блокировать доступ к ресурсу, который используется несколькими процессами, вам необходимо использовать Mutex или семафор.
Класс Mutex - это .Net-оболочка вокруг механизма блокировки уровня ОС.
Обзор примитивов синхронизации