2009-10-03 2 views
4

Я пишу службу Windows, которая может удалить файл в какой-то момент. Поскольку служба имеет дело с обычным файловым IO, возможно, что файл может использоваться во время удаления.Как определить, что файл используется перед удалением?

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

try 
{ 
    File.Delete(file); 
    Status = ResponseStatus.Ok; 
} 
catch (IOException e) 
{ 
    Status = ResponseStatus.FileInUse; 
} 
finally 
{ 
    return Status; 
} 

Как определить, используется ли файл без использования исключения?

+1

Что не так с вашим нынешним подходом? –

+0

@PK, я не уверен, что это лучшее решение. Я решил, что я попрошу толпу и объединить мозг, безусловно, придумает лучший способ решить проблему. – Vadim

+0

@PK: Идея его нынешнего подхода (удалить и посмотреть, не сработала ли она) верна, но он не обязательно должен использовать здесь «Исключение». Если он делает это во многих файлах, то накладные расходы на основе «Исключения» могут быть существенными. Импорт 'DeleteFile' должен быть быстрее, поскольку он все еще может проверить успех, но не будет обременен накладными расходами на разматывание стека и т. Д. –

ответ

13

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

Код, который у вас уже есть, является именно таким способом.

2

Если вы просто хотите проверить, было ли удаление успешным без исключения, вам просто нужно объявить P/Invoke для функции DeleteFile.

[DLLImport("Kernel32.dll", SetLastError = true)] 
public static extern bool DeleteFile(string fileName); 

Это вернет true, если удаление было успешным и false, если это не было. Если вы хотите указать конкретный код ошибки, вы можете позвонить по телефону Marshal.GetLastWin32Error()

3

Как говорит Ричи, ловить исключения, вероятно, лучший подход здесь.

Но что, если вы хотите удалить 10 файлов, и вы не хотите, чтобы он провалился на полпути? Вам действительно нужен какой-то способ защиты общей транзакции. Так что is полезно, чтобы иметь возможность пассивно проверять, используется ли файл. Вы можете определить, используется ли файл (или только для чтения, что также делает его неуязвимым), просто пытаясь открыть его для записи (а затем, если вам это удастся, немедленно его закрыть). Это само по себе не гарантирует, что последующая попытка удаления будет успешной.

Другие подходы, которые могли бы работать: - переместить/переименовать файл (ы) перед удалением (поместите их в безопасное место, чтобы вы знали, что впоследствии их нельзя открыть другим процессом), чтобы вы могли «отменить «транзакция, если какая-либо операция отдельных операций не выполняется. - поймать исключение и очереди будущей попытки удалить файл (либо в вашей собственной программе, или вы можете пометить файл для автоматического удаления с помощью Windows, при следующей перезагрузке)

+0

+1: Хорошие точки. – RichieHindle

+0

+1. Хорошо помнить об этом. Однако в моем случае это не применяется. Служба собирается удалить один файл за раз. – Vadim

3

Расширение на правильный ответ Ричи

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

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

if (File.SomeTypeOfCheck(somePath) { 
    File.DoSomeOperation(somePath); 
} 
Смежные вопросы