2008-10-21 3 views
25

С помощью следующего кода чтения файла:В C#, если 2 процесса считывают и записывают в один и тот же файл, каков наилучший способ избежать исключений блокировки процесса?

using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None)) 
{ 
    using (TextReader tr = new StreamReader(fileStream)) 
    { 
     string fileContents = tr.ReadToEnd(); 
    } 
} 

и следующий код записи файла:

using (TextWriter tw = new StreamWriter(fileName)) 
{ 
    tw.Write(fileContents); 
    tw.Close(); 
} 

следующие данные исключения рассматриваются:

Процесс не может получить доступ к файлу 'c: \ temp \ myfile.txt', потому что это , используемый другим процессом.

Каков наилучший способ избежать этого? Должен ли читатель повторять попытку после получения исключения или есть лучший способ?

Обратите внимание, что в процессе чтения используется файл FileSystemWatcher, чтобы узнать, когда файл был изменен.

Также обратите внимание, что в данном случае я не ищет альтернативные способы совместного использования строк между двумя процессами.

ответ

34

Вы можете открыть файл для записи и только заблокировать доступ к записи, тем самым позволяя другим пользователям читать файл.

Например,

using (FileStream stream = new FileStream(@"C:\Myfile.txt", FileMode.Open, FileAccess.ReadWrite, FileShare.Read)) 
{ 
    // Do your writing here. 
} 

Другой доступ к файлам только открывает файл для чтения и не писать, и позволяет READWRITE обмен.

using (FileStream stream = new FileStream(@"C:\Myfile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
{ 
    // Does reading here. 
} 

Если вы хотите, чтобы убедиться, что читатели всегда будут читать последнюю дату файла, вам нужно будет либо использовать блокирующий файл, который указывает, что кто-то запись в файл (хотя вы можете получить состояние гонки если они не были тщательно реализованы) или убедитесь, что вы блокируете совместное использование писем при открытии для чтения и обработки исключения, чтобы повторить попытку, пока не получите эксклюзивный доступ.

2

Для этого вы можете использовать объект Mutex.

+0

Спасибо за быстрый ответ. Что делать, если процессы находятся в разных системах, и файл делится по сети? – Iain 2008-10-21 14:33:51

+0

Хе-хе, тогда это не будет работать. Использовать нулевой байтовый файл «блокировки», например, службы Linux, делает это :) – leppie 2008-10-21 14:38:11

6

Если вы создали именованный Mutex, вы можете определить мьютексы в приложении для записи и попросите приложение для чтения до тех пор, пока не будет выпущен мьютекс.

Так что в процессе уведомления, который в настоящее время работает с FileSystemWatcher, просто проверьте, нужно ли ждать мьютекса, если да, то он будет ждать, а затем обрабатывать.

Вот VB example of a Mutex вот так, что я нашел, должно быть достаточно легко конвертировать в C#.

2

Получить свой процесс, чтобы проверить статус файла, если он записывается. Вы можете сделать это за счет наличия файла блокировки (т. Е. Наличие этого другого файла, который может быть пустым, предотвращает запись в основной файл).

Даже это не является отказоустойчивым, поскольку оба процесса могут одновременно создавать файл блокировки, но вы можете проверить это, прежде чем совершать запись.

Если ваш процесс встречает файл блокировки, попробуйте просто спать/ждать и повторить попытку с заранее заданным интервалом в будущем.

1

Напишите временному файлу, когда закончите запись, переименуйте/переместите файл в нужное место и/или имя, которое ищет читатель.

3

Есть ли какая-либо особая причина для открытия файла с помощью FileShare.None? Это предотвратит открытие файла любым другим процессом.

FileShare.Write или FileShare.ReadWrite должен позволить другому процессу (с разрешениями) открывать и писать в файл во время его чтения, однако вам придется следить за тем, как файл меняется под вами во время чтения это - просто буферизация содержимого при открытии может помочь здесь.

Все эти ответы, впрочем, одинаково верны - лучшее решение зависит от того, что вы пытаетесь сделать с файлом: если важно прочитать его, пока оно не изменится, а затем заблокируйте его и обрабатывать последующее исключение в своем письменном коде; если важно одновременно читать и писать, а затем изменить константу FileShare.

2

Читателю и писателю необходимы механизмы повторной попытки. Также FileShare должен быть установлен в FileShare.read для читателей и FileShare.none для писателя. Это должно гарантировать, что читатели не читают файл во время записи.

Читатель (за исключением повторных попыток) становится

using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) 
{ 
    using (TextReader tr = new StreamReader(fileStream)) 
    { 
     string fileContents = tr.ReadToEnd(); 
    } 
} 

Автор (за исключением повторных попыток) становится:

FileStream fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None); 
using (TextWriter tw = new StreamWriter(fileStream)) 
{ 
    tw.Write(fileContents); 
    tw.Close(); 
} 
1

Самое лучшее, что нужно сделать, это поставить протокол приложения поверх файла передачи/собственности. Механизм «lock-file» - это старый хакер UNIX, который существует уже целую вечность. Лучшее, что нужно сделать, это просто «передать» файл читателю. Есть много способов сделать это. Вы можете создать файл со случайным именем файла, а затем «дать» это имя читателю. Это позволит автору асинхронно писать другой файл. Подумайте, как работает «веб-страница». Веб-страница имеет ссылку на дополнительную информацию в ней, изображения, сценарии, внешний контент и т. Д. Сервер передает вам эту страницу, потому что это согласованное представление о «ресурсе», который вы хотите. Затем ваш браузер переходит к соответствующему контенту, основываясь на описании страницы (HTML-файле или другом возвращенном контенте), а затем передает то, что ему нужно.

Это наиболее устойчивый тип механизма совместного использования. Запишите файл, поделитесь им, перейдите к следующему файлу. Часть «совместного использования имени» - это атомная рука, которая гарантирует, что обе стороны (читатель и писатель) согласны с тем, что контент «завершен».

 Смежные вопросы

  • Нет связанных вопросов^_^