FileSystemWatcher.WaitForChanged возвращается, но файл все еще заблокирован
-
05-09-2019 - |
Вопрос
У меня есть программа, которая отправляет документ в драйвер принтера PDF, и этот драйвер печатает в определенный каталог.После печати я хочу прикрепить PDF-файл к электронному письму (MailMessage) и отправить его.
Прямо сейчас я отправляю документ на принтер (который запускает новый процесс), а затем вызываю FileSystemWatcher.WaitForChanged(WaitForChangedResult.Created), но когда объект создается, его «печать» все еще не завершена, и принтер PDF все еще имеет блокирую его, выдавая ошибку, когда я пытаюсь прикрепить этот файл к электронному письму.
- Я рассматривал простой Thread.Sleep(2000) или что-то еще, но это далеко не идеально.
- Я подумывал о том, чтобы поместить код вложения в блок try/catch и зациклить его в случае неудачи, но опять же, это просто плохие новости.
Я не могу придумать элегантного решения.
Решение
WaitForChanges — это ожидание созданного события как у вас это закодировано.По мере создания документа вы получаете уведомление:это не означает, что файл полностью записан и блокировка снята.
К сожалению, я не знаю другого хорошего решения, кроме периодического опроса файла.Если бы было событие «все блокировки сняты», вы могли бы использовать его, но его нет.
Я только что проверил наш дамп PDF в коде каталога, и мы используем WaitForChanges только для обнаружения начала нового файла.Затем мы используем try {} catch {}, где catch (не получив права на файл) повторно отправляет попытку в поддерживаемую нами очередь:каждая попытка «отменяется» на более длительное время, поэтому первая попытка — через 1 секунду после обнаружения файла, вторая — через 2 секунды, затем 4, 8 и т. д.Это уменьшает количество повторных попыток обработки больших файлов, сохраняя при этом достаточную скорость реагирования на более короткие файлы.
Другие советы
Что ж, пока наблюдатель наблюдает за файлом и сообщает вам, когда он изменяется, вы можете просто игнорировать уведомления об изменениях, которые появляются, пока файлы все еще заблокированы (все еще записываются), и ждать окончательного уведомления об изменении, которое будет сигнализировать о последнее событие записи, после которого файл должен быть доступен (после чего вы можете наконец отключить часы).
Кроме этого, я не уверен, что вы можете сделать, потому что у наблюдателя нет события «закрытый файл» AFAIK.
AFAIK нет способа проверить блокировки файлов без обработки ошибок.
Может быть, принтер PDF запускается с новым процессом?Тогда вы сможете отслеживать этот процесс, и когда он завершится, ваш файл будет разблокирован.
Если вы используете для этого Adobe Acrobat, вы можете сгенерировать PDF-файл с помощью Acrodist.exe (мне сразу пришло в голову, вам нужен переключатель /N), а затем дождаться завершения порожденного процесса.