Синхронизировать запись в файл на уровне файловой системы - PullRequest
4 голосов
/ 18 февраля 2011

У меня есть текстовый файл, и несколько потоков / процессов будут писать в него (это файл журнала).

Файл иногда поврежден из-за одновременных записей.

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

Я знаю, что можно использовать блокировки (мьютекс для нескольких процессов) и синхронизировать запись в этот файл, но я предпочитаю открыть файл в правильном режиме и оставить задачу на System.IO.

Возможно ли это? Какова лучшая практика для этого сценария?

Ответы [ 3 ]

4 голосов
/ 18 февраля 2011

Лучше всего использовать только замки / mutexex. Это простой подход, он работает, и вы можете легко понять это и обосновать это.

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

2 голосов
/ 18 февраля 2011

Насколько мне известно, Windows не имеет то, что вы ищете.Не существует объекта дескриптора файла, который выполняет автоматическую синхронизацию, блокируя всех других пользователей во время записи в файл.

Если регистрация ведется в три этапа: открыть файл, записать, закрыть файл, тогда выПотоки пытаются открыть файл в монопольном режиме (FileShare.None), перехватить исключение, если не удается открыть, и затем повторить попытку до успеха.В лучшем случае я нашел это утомительным.

В моих программах, которые ведут журнал из нескольких потоков, я создал TextWriter потомка, который по сути является очередью.Потоки вызывают методы Write или WriteLine для этого объекта, который форматирует выходные данные и помещает их в очередь (используя BlockingCollection).Отдельный поток ведения журнала, который ставит в очередь - извлекает из него вещи и записывает их в файл журнала.Это имеет несколько преимуществ:

  • Потоки не должны ждать друг друга для записи
  • Только один поток пишет в файл
  • Этотривиально вращать журналы (т. е. запускать новый файл журнала каждый час и т. д.)через процессы будет намного сложнее.Я никогда даже не думал о том, чтобы попытаться поделиться файлом журнала между процессами.Если бы мне это было нужно, я бы создал отдельное приложение (сервис регистрации).Это приложение будет выполнять фактическую запись, а другие приложения будут передавать строки для записи.Опять же, это гарантирует, что я не могу все испортить, и мой код остается простым (т.е. нет явного кода блокировки в клиентах).
1 голос
/ 18 февраля 2011

вы можете использовать File.Open() со значением FileShare, установленным на None, и заставить каждый поток ждать, если он не сможет получить доступ к файл.

...