Совместное использование файловых блокировок - PullRequest
1 голос
/ 05 марта 2010

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

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

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

Суть этого подхода показана ниже (я упустил обработку ошибок для простоты):

using(FileStream fs = File.Open(myFile, FileMode.Open, FileAccess.ReadWrite, (FileShare.Read | FileShare.Delete))
{
//Do work
}

В1: Мой процесс теперь заблокирован для этого файла.Я думал, что это означало бы, что я мог бы тогда получить доступ к тому же файлу (без использования потока) и все еще иметь правильный доступ к нему, но на основании тестирования кажется, что у меня есть только преимущества блокировки через поток.Это правильно?

(Например, прежде чем я включил FileShare.Delete, File.Delete (myFile) не удалось)

Приведенная выше блокировка в конечном итоге использует разрешение «Запись» для определениякакая служба имеет файл, но предназначена для того, чтобы другие процессы могли по-прежнему читать файл.Это связано с тем, что процесс, имеющий блокировку, пытается проверить, является ли файл допустимым zip-файлом, который использует стороннюю библиотеку (Xceed.Zip).Однако это не помогает, говоря, что файл «используется другим процессом» .Используя отражатель, я в конечном итоге обнаружил, что проблемный вызов:

stream = this.m_info.Open(FileMode.Open, FileAccess.Read, FileShare.Read);

Теперь я ожидал, что это сработает, так как он хочет только прочитать файл, но он не работает.Причина, по-видимому, изложена в аналогичном вопросе .Однако, поскольку это сторонний API, я не могу изменить их код для использования ReadWrite.

Q2: Есть ли способ, которым я могу правильно заблокировать файл, чтобы он не был подхвачендругие сервисы, но его все еще можно проверить как zip-файл с использованием внешнего API?

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

1 Ответ

0 голосов
/ 06 марта 2010

Если вы планируете реагировать на эту ситуацию, обрабатывая UnauthorizedAccessException, я думаю, вы делаете серьезную ошибку.

Это можно сделать, предварительно переименовав файлы. Например, вы можете настроить свою службу только для чтения файлов, имя которых имеет формат «Имя файла.ГГГГММДД.txt». Перед обработкой файла вы можете переименовать его в «Filename.YYYYMMDD.processing». Затем после обработки файла вы переименовываете его в «Filename.YYYYMMDD.done».

Вы даже можете сделать еще один шаг, сделав другой сервис, который ставит в очередь имена файлов. Этот сервис будет FileSystemWatcher, который прослушивает операции FileAdd. Получив это событие, он переходит в очередь с именем файла в глобальную очередь сообщений. Тогда каждый из ваших сервисов будет просто удалять имена файлов, и вам больше не придется беспокоиться о параллельном доступе.

НТН

...