Я пишу программу на C #, которая должна повторно получить доступ к 1 файлу изображения. В большинстве случаев это работает, но если мой компьютер работает быстро, он попытается получить доступ к файлу до его сохранения в файловой системе и выдаст ошибку: «Файл используется другим процессом» .
Я хотел бы найти способ обойти это, но все мои поиски в Google привели только к созданию проверок с использованием обработки исключений. Это против моей религии, поэтому мне было интересно, есть ли у кого-нибудь лучший способ сделать это?
Ответы:
Обновлено примечание по этому решению : проверка с использованием
FileAccess.ReadWrite
файла «Только для чтения» завершится ошибкой, поэтому решение было изменено для проверки с помощьюFileAccess.Read
. Хотя это решение работает, потому что попытка выполнить проверкуFileAccess.Read
не удастся, если у файла есть блокировка записи или чтения, однако это решение не будет работать, если у файла нет блокировки записи или чтения, т.е. он был открыт (для чтения или записи) с доступом FileShare.Read или FileShare.Write.ОРИГИНАЛ: Я использовал этот код в течение последних нескольких лет, и у меня не было никаких проблем с ним.
Поймите, что вы колеблетесь с использованием исключений, но вы не можете избежать их все время:
источник
public static bool IsLocked(this FileInfo file) {/*...*/}
.Вы можете страдать от состояния гонки потоков, в котором есть документированные примеры использования в качестве уязвимости безопасности. Если вы проверите, что файл доступен, но затем попытаетесь использовать его, вы можете выбросить его в этот момент, который злоумышленник может использовать для принудительного использования и использования вашего кода.
Ваша лучшая ставка - это попытка catch / finally, которая пытается получить дескриптор файла.
источник
Используйте это, чтобы проверить, заблокирован ли файл:
Из соображений производительности я рекомендую прочитать содержимое файла в той же операции. Вот некоторые примеры:
Попробуйте сами:
источник
IOException
, а не на общем,Exception
а затем тест на тип.IOException
после общего. Общий поймает все, что проходит, а конкретныйIOException
всегда будет одиноким. Просто поменяйте местами.Просто используйте исключение по назначению. Подтвердите, что файл используется, и повторите попытку несколько раз, пока ваше действие не будет завершено. Это также наиболее эффективно, потому что вы не тратите время на проверку состояния, прежде чем действовать.
Используйте функцию ниже, например
Повторно используемый метод, который истекает через 2 секунды
источник
Возможно, вы могли бы использовать FileSystemWatcher и наблюдать за событием Changed.
Я сам этим не пользовался, но, возможно, стоит попробовать. Если файловый системный наблюдатель оказывается немного тяжелым для этого случая, я бы пошел на цикл try / catch / sleep.
источник
Вы можете вернуть задачу, которая дает вам поток, как только он становится доступным. Это упрощенное решение, но это хорошая отправная точка. Это потокобезопасно.
Вы можете использовать этот поток как обычно:
источник
GetStreamAsync()
?единственный известный мне способ - использовать API эксклюзивной блокировки Win32, который не слишком быстр, но примеры существуют.
Большинство людей, для простого решения этой проблемы, просто пробуют / ловят / спят петлями.
источник
Надеюсь это поможет!
источник
Принятые ответы, приведенные выше, сталкиваются с проблемой, когда файл, открытый для записи в режиме FileShare.Read, или файл с атрибутом «Только чтение», код не будет работать. Это модифицированное решение работает наиболее надежно, имея в виду две вещи (как и для принятого решения):
Помня вышеупомянутое, это проверяет, заблокирован ли файл для записи или заблокирован, чтобы предотвратить чтение :
источник
Помимо работы с 3-строчками и просто для справки: если вы хотите получить полную информацию - в Microsoft Dev Center есть небольшой проект:
https://code.msdn.microsoft.com/windowsapps/How-to-know-the-process-704839f4
Из введения:
Он работает, подключившись к «Перезапустить сеанс менеджера».
Это может быть немного слишком сильно для ваших конкретных нужд ... Но если это то, что вы хотите, продолжайте и возьмите vs-проект.
источник
По моему опыту, вы обычно хотите сделать это, затем «защитить» свои файлы, чтобы сделать что-то необычное, а затем использовать «защищенные» файлы. Если у вас есть только один файл, который вы хотите использовать подобным образом, вы можете использовать трюк, который объясняется в ответе Джереми Томпсона. Однако, если вы попытаетесь сделать это для большого количества файлов (скажем, например, когда пишете установщик), вам будет очень больно.
Очень элегантный способ решить эту проблему - использовать тот факт, что ваша файловая система не позволит вам изменить имя папки, если один из файлов там используется. Держите папку в той же файловой системе, и она будет работать как шарм.
Обратите внимание, что вы должны знать об очевидных способах его использования. В конце концов, файлы не будут заблокированы. Также имейте в виду, что есть и другие причины, которые могут привести
Move
к сбою в работе. Очевидно, что правильная обработка ошибок (MSDN) может помочь здесь.Что касается отдельных файлов, я бы придерживался предложения о блокировке от Джереми Томпсона.
источник
FileShare
и проверки блокировки.Вот код, который, насколько я могу судить, делает то же самое, что и принятый ответ, но с меньшим количеством кода:
Однако я думаю, что это более надежно сделать следующим образом:
источник
Вы можете использовать мою библиотеку для доступа к файлам из нескольких приложений.
Вы можете установить его из nuget: Install-Package Xabe.FileLock
Если вы хотите больше информации об этом, проверьте https://github.com/tomaszzmuda/Xabe.FileLock
Метод fileLock.Acquire вернет true, только если может заблокировать файл исключительно для этого объекта. Но приложение, которое загружает файл, должно делать это и при блокировке файла. Если объект недоступен, метод возвращает false.
источник
Когда-то мне нужно было загружать PDF-файлы в онлайн-архив. Но резервное копирование не удастся, если пользователь откроет файл в другой программе (например, в программе чтения PDF). В спешке я попытался ответить на несколько лучших вопросов в этой теме, но не смог заставить их работать. Что мне помогло, так это попытка переместить файл PDF в его собственный каталог . Я обнаружил, что это не получится, если файл будет открыт в другой программе, и если перемещение будет успешным, операция восстановления не потребуется, как если бы он был перемещен в отдельный каталог. Я хочу опубликовать свое базовое решение на случай, если оно может быть полезно для других конкретных случаев использования.
источник
Мне интересно посмотреть, вызывает ли это какие-либо рефлексы WTF. У меня есть процесс, который создает и впоследствии запускает документ PDF из консольного приложения. Однако я имел дело со слабостью, когда, если бы пользователь запускал процесс несколько раз, генерируя один и тот же файл, не закрывая предварительно сгенерированный файл, приложение выдает исключение и умирает. Это было довольно частым явлением, потому что имена файлов основаны на номерах коммерческих предложений.
Вместо того, чтобы терпеть неудачу в такой неблагодарной манере, я решил положиться на автоматическое увеличение версий файлов:
Возможно,
catch
блоку нужно уделить больше внимания, чтобы убедиться, что я ловлю правильные исключения IOException. Я, вероятно, также очистлю хранилище приложения при запуске, так как эти файлы в любом случае должны быть временными.Я понимаю, что это выходит за рамки вопроса ОП просто проверять, используется ли файл, но это действительно была проблема, которую я искал, когда прибыл сюда, так что, возможно, это будет полезно для кого-то еще.
источник
Поможет ли что-нибудь подобное?
источник
Попробуйте переместить / скопировать файл во временную папку. Если вы можете, у него нет блокировки, и вы можете безопасно работать в временном каталоге, не получая блокировки. В противном случае просто попробуйте переместить его снова через x секунд.
источник
Я использую этот обходной путь, но у меня есть промежуток времени между проверкой блокировки файла с помощью функции IsFileLocked и открытием файла. В этот промежуток времени какой-то другой поток может открыть файл, поэтому я получу IOException.
Итак, я добавил дополнительный код для этого. В моем случае я хочу загрузить XDocument:
Что вы думаете? Могу ли я что-то изменить? Может быть, мне не нужно было использовать функцию IsFileBeingUsed вообще?
Спасибо
источник