как лучше подождать, пока освободится файл - PullRequest
9 голосов
/ 27 марта 2009

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

Но мой вопрос в том, как мне точно знать, что файл заблокирован и что это не очередной IOExcetpion, который происходит.

Ответы [ 6 ]

5 голосов
/ 27 марта 2009

Когда вы открываете файл для чтения в .NET, он в какой-то момент попытается создать дескриптор файла с помощью API-функции CreateFile , которая устанавливает код ошибки , который можно использовать. чтобы понять, почему это не удалось:

const int ERROR_SHARING_VIOLATION = 32;
try
{
    using (var stream = new FileStream("test.dat", FileMode.Open, FileAccess.Read, FileShare.Read))
    {
    }
}
catch (IOException ex)
{
    if (Marshal.GetLastWin32Error() == ERROR_SHARING_VIOLATION)
    {
        Console.WriteLine("The process cannot access the file because it is being used by another process.");
    }
}
4 голосов
/ 27 марта 2009

Есть полезная дискуссия по группам Google , которую вы действительно должны прочитать. Один из вариантов близок к Дарину; однако, чтобы гарантировать, что вы получите правильную ошибку win32, вам действительно следует самостоятельно вызывать win32 OpenFile () API (иначе вы действительно не знаете, какую ошибку вы получаете).

Другой способ - проанализировать сообщение об ошибке: произойдет сбой, если приложение запущено на другой языковой версии.

Третий вариант - взломать класс исключений, чтобы отразить фактический HRESULT.

Ни одна из альтернатив не является настолько привлекательной: иерархия IOException выиграет от еще нескольких подклассов IMHO.

0 голосов
/ 27 марта 2009

Вы имеете в виду, что вы читаете и пишете в файл? Или что внешнее приложение пишет в него.

Если вы делаете чтение и запись, то я предполагаю, что вы делаете это в разных потоках, и в этом случае взгляните на класс ReaderWriteLock, который сделает это за вас и предоставит время ожидания. *

http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlock.aspx

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

fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read));
0 голосов
/ 27 марта 2009

Вы можете открыть его (как описано bezieur), а затем попытаться заблокировать разделы (или весь файл): http://www.java2s.com/Code/VB/File-Directory/Lockandunlockafile.htm

0 голосов
/ 27 марта 2009

Вы можете сравнить с типом IOException, чтобы проверить и проверить, не является ли это чем-то другим

Например

if (ex is FileNotFoundException)

Возможно, вы захотите посмотреть справку по System.IO. Многие исключения в этом классе наследуются от IOException . Вне проверки, чтобы увидеть, является ли это другим типом исключения, вам, возможно, придется посмотреть в сообщении описания или вы могли бы сделать вызов Win32 API в shell32.dll. Там может быть функция, чтобы проверить, заблокирован ли файл.

Также, если вам абсолютно необходимо ждать, вы можете использовать цикл, но если вы хотите выполнять другие действия во время ожидания, используйте асинхронный поток.

0 голосов
/ 27 марта 2009

Для чтения данных вы можете сделать:

использование (FileStream fs = new FileStream (fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) {....}

и сохранить в файл:

с использованием (FileStream fs = new FileStream (fileName, FileMode.Append, FileAccess.Write, FileShare.Read | FileShare.Delete)) {...}

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

...