2009-05-18 3 views
648

Я пишу программу на C#, которая требует многократного доступа к 1 файлу изображения. Большую часть времени он работает, но если мой компьютер работает быстро, он попытается получить доступ к файлу, прежде чем он будет сохранен обратно в файловую систему, и выкинет ошибку: «Файл используется другим процессом».Есть ли способ проверить, используется ли файл?

Я хотел бы найти способ обойти это, но весь мой Googling только дал возможность создавать проверки с помощью обработки исключений. Это противоречит моей религии, поэтому мне было интересно, есть ли у кого лучший способ сделать это?

+23

Хорошо, вы можете проверить это, изучив все открытые ручки в системе. Однако, поскольку Windows является многозадачной операционной системой, есть вероятность, что сразу после запуска кода, чтобы определить, открыт ли файл, и вы считаете, что это не так, код процесса начинает использовать этот файл, а затем к тому моменту, когда вы пытаетесь используйте его, вы получите сообщение об ошибке. Но сначала нет ничего плохого в проверке; просто не предполагайте, что он не используется, когда вам это действительно нужно. – BobbyShaftoe

+3

Но только для этой конкретной проблемы; Я бы рекомендовал не изучать дескрипторы файлов и просто попробовать несколько предустановленных чисел, скажем, 3-5 перед сбоем. – BobbyShaftoe

+0

Как создается этот файл изображения? Можете ли вы остановить/спать/приостановить свою программу до тех пор, пока поколение не будет завершено? Это, безусловно, лучший способ справиться с ситуацией. Если нет, то я не думаю, что вы можете избежать использования обработки исключений. – Catchwa

ответ

418

Обновлено Примечание на этом решении: Проверка с FileAccess.ReadWrite потерпит неудачу только для чтения файлов, так что решение было изменено, чтобы проверить с FileAccess.Read. Хотя это решение работает, потому что попытка проверить с помощью FileAccess.Read не удастся, если в файле есть запись или блокировка чтения на нем, однако это решение не будет работать, если в файле нет блокировки записи или чтения, т. Е. (для чтения или записи) с доступом FileShare.Read или FileShare.Write.

ОРИГИНАЛ: Я использовал этот код последние несколько лет, и у меня не было никаких проблем с ним.

Понять ваши сомнения по поводу использования исключений, но вы не можете избежать их все время:

protected virtual bool IsFileLocked(FileInfo file) 
{ 
    FileStream stream = null; 

    try 
    { 
     stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None); 
    } 
    catch (IOException) 
    { 
     //the file is unavailable because it is: 
     //still being written to 
     //or being processed by another thread 
     //or does not exist (has already been processed) 
     return true; 
    } 
    finally 
    { 
     if (stream != null) 
      stream.Close(); 
    } 

    //file is not locked 
    return false; 
} 
+51

Это отличное решение, но у меня есть один комментарий - вы можете открыть файл с режимом доступа FileAccess.Read, так как ReadWrite всегда будет терпеть неудачу, если файл будет доступен только для чтения. – adeel825

+5

Хороший ответ, но проблема в том, что файл не может существовать фактически, что приведет к исключению FileNotFound - это исключение IOException. Блок catch IOException поймает это, и результат метода интерпретирует это как заблокированный файл, когда на самом деле файл фактически не существует - это может привести к затруднению диагностики ошибок. Хитрое из перспективы API - возможно, API должен быть GetFileState, который возвращает перечисление: Locked, NotFound, KnockYourselfOut.:) Конечно, может быть поднято UnauthorizedAccessException, которое не является исключением IOException ... –

+185

-1. Это плохой ответ, потому что файл может быть заблокирован другим потоком/процессом после его закрытия в IsFileLocked и до того, как ваш поток получит возможность открыть его. – Polyfun

5

Единственный способ, которым я знаю, - использовать API исключительной блокировки Win32, который не слишком быстр, но существуют примеры.

Большинство людей, для простого решения этого, просто попробуйте/поймать/спать.

+0

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

6

Возможно, вы можете использовать FileSystemWatcher и следить за событием Changed.

Я не использовал это сам, но это может стоить того. Если для этого случая файловая система будет немного тяжелой, я бы пошел на цикл try/catch/sleep.

+0

FileSystemWatcher не обрабатывает множество изменений в то же время очень хорошо, хотя, поэтому будьте осторожны с этим. –

+1

Кстати, вы, ребята, заметили при отладке и просмотре потоков, которые MS называет своей FSW «FileSystemWather»? Что же это такое? – devlord

+1

Использование FileSystemWatcher не помогает, поскольку события Create и Changed повышаются в начале создания/изменения файла. Даже небольшим файлам требуется больше времени для записи и закрытия операционной системой, чем приложение .NET должно запускаться через обратный вызов FileSystemEventHandler. Это так печально, но нет другого выбора, кроме как оценить время ожидания перед доступом к файлу или запуском в циклы исключений ... – 2011-07-08 12:29:25

497

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

Ваш лучший выбор - попытка catch/finally, которая пытается получить дескриптор файла.

try 
{ 
    using (Stream stream = new FileStream("MyFilename.txt", FileMode.Open)) 
    { 
     // File/Stream manipulating code here 
    } 
} catch { 
    //check here why it failed and ask user to retry if the file is in use. 
} 
+98

+1. Нет никакого 100% безопасного способа «узнать, используется ли файл», потому что миллисекунды после проверки, файл может быть не использован больше или наоборот. Вместо этого вы просто открываете файл и используете его, если нет исключений. –

+7

Слишком плохо .NET не поддерживает CAS. Что-то вроде TryOpenFile (Ref FileHandle), который возвращает успех/сбой. Всегда должно быть обход, не полагаться только на обработку исключений. Интересно, как это делает Microsoft Office. – TamusJRoyce

+2

Главное, чтобы понять здесь, что этот API просто использует API окон для получения дескриптора файла. Таким образом, им необходимо перевести код ошибки, полученный из API C, и передать его в исключение для броска. У нас есть обработка исключений в .Net, так почему бы не использовать его. Таким образом, вы можете написать чистый путь вперед в своем коде и оставить обработку ошибок в отдельном коде. – Spence

-1

Попробуйте переместить/скопировать файл в папку temp. Если вы можете, у него нет блокировки, и вы можете безопасно работать во временном каталоге без получения блокировок. Else просто попробуйте переместить его за x секунд.

+0

Что делать, если что-то блокирует его сразу после перемещения файла? – jcolebrand

+0

@ jcolebrand блокирует что? тот, который вы скопировали? Или тот, который вы положили во временную директорию? – Cullub

+4

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

-14

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

я поставил счетчик, чтобы продолжать пытаться в 100 раз, чтобы остановить бесконечный цикл.

Смотрите ниже ...

private void uploadFiles(string filename) 
    { 
     try 
     { 
      string fromFileAndPath = Properties.Settings.Default.Path + "\\" + filename; 
      string toFileAndPath = Properties.Settings.Default.CopyLocation + "\\" + filename; 
      if (!File.Exists(toFileAndPath)) 
      { 
       FileInfo imgInfo = new FileInfo(fromFileAndPath); 
       bool copied = false; 
       int counter = 0; 
       while (!copied && counter < 100) //While was added as I was getting "The process cannot access the file because it is being used by another process" errors. 
       { 
        try 
        { 
         counter++; 
         imgInfo.CopyTo(toFileAndPath); 
         copied = true; 
        } 
        catch 
        { 
         //If it cannot copy catch 
        } 
       } 
       if (counter > 100) 
        throw new Exception("Unable to copy file!"); 
       Thread.Sleep(1); 
      } 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show("An error occurred: " + ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error); 
     } 
    } 
+9

Если файл заблокирован, вы пытаетесь открыть файл 100 раз в цикле блокировки ... Это затормозит вашу программу от использования во время этих проверок, и, кстати, совершенно бессмысленно, потому что CPU может запускать только один процесс в время. Нет гарантии, что ОС даже переключится на другой процесс, чтобы файл закрылся в течение этого цикла! Вы могли бы также проверить миллион раз; файл не будет закрыт до тех пор, пока ваша программа не выведет управление CPU на другой процесс. Вам следует запланировать асинхронный обратный вызов, который будет проверяться снова через определенное время. – Lakey

+0

Я добавил спать, чтобы решить проблему. – mafu

+4

Использование сна, чтобы попытаться смоделировать резьбовые функции? (lol) Кроме того, это почти ничего не меняет. Это всего лишь хип-хоп, который в лучшем случае будет непоследовательным. Весь дизайн просто плох. Без обид. – Lakey

15

Вот версия PowerShell принятого ответа.

function IsFileLocked($filename) { 

    $result = $false 

    $fileinfo = [System.IO.FileInfo] (gi $filename).fullname 

    try { 
     $stream = $fileInfo.Open([System.IO.FileMode]"Open",[System.IO.FileAccess]"ReadWrite",[System.IO.FileShare]"None") 
     $stream.Dispose() 
    } catch [System.IO.IOException] { 
     $result = $true 
    } 

    $result 
} 
+3

И как здесь важна силовая часть? – BartoszKP

+1

Он отвечает на вопрос «Есть ли способ проверить, используется ли файл?». Оригинальный вопрос продолжает показывать, что они были заинтересованы в C#, я нашел вопрос SO, когда искал что-то, что нужно сделать из скрипта. –

+1

Возможно, другой вопрос с тегом [tag: powershell] будет в порядке? Здесь кажется шумным и не по теме. – BartoszKP

4
static bool FileInUse(string path) 
    { 
     try 
     { 
      using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate)) 
      { 
       fs.CanWrite 
      } 
      return false; 
     } 
     catch (IOException ex) 
     { 
      return true; 
     } 
    } 

string filePath = "C:\\Documents And Settings\\yourfilename"; 
bool isFileInUse; 

isFileInUse = FileInUse(filePath); 

// Then you can do some checking 
if (isFileInUse) 
    Console.WriteLine("File is in use"); 
else 
    Console.WriteLine("File is not in use"); 

Надеется, что это помогает!

+7

Фактическая проверка, которую вы выполняете, в порядке; ввод его внутрь функции вводит в заблуждение. Вы не хотите использовать такую ​​функцию перед открытием файла. Внутри функции файл открывается, проверяется и закрывается. Затем программист ДОПУСКАЕТ, что файл STILL одобрен для использования и пытается открыть его для использования. Это плохо, потому что он может быть использован и заблокирован другим процессом, который был поставлен в очередь, чтобы открыть этот файл. Между 1-м разом он был открыт (для проверки) и 2-й раз, когда он был открыт (для использования), ОС могла бы выполнить ваш процесс и запустить другой процесс. – Lakey

-3

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

Итак, я добавил дополнительный код для этого. В моем случае я хочу загрузить XDocument:

 XDocument xDoc = null; 

     while (xDoc == null) 
     { 
      while (IsFileBeingUsed(_interactionXMLPath)) 
      { 
       Logger.WriteMessage(Logger.LogPrioritet.Warning, "Deserialize can not open XML file. is being used by another process. wait..."); 
       Thread.Sleep(100); 
      } 
      try 
      { 
       xDoc = XDocument.Load(_interactionXMLPath); 
      } 
      catch 
      { 
       Logger.WriteMessage(Logger.LogPrioritet.Error, "Load working!!!!!"); 
      } 
     } 

Как вы думаете? Могу ли я что-то изменить? Может быть, мне не нужно было использовать функцию IsFileBeingUsed?

Благодаря

+3

Что такое IsFileBeingUsed? исходный код IsFileBeingUsed? – Kiquenet

76

Используйте это, чтобы проверить, если файл заблокирован:

using System.IO; 
using System.Runtime.InteropServices; 
internal static class Helper 
{ 
const int ERROR_SHARING_VIOLATION = 32; 
const int ERROR_LOCK_VIOLATION = 33; 

private static bool IsFileLocked(Exception exception) 
{ 
    int errorCode = Marshal.GetHRForException(exception) & ((1 << 16) - 1); 
    return errorCode == ERROR_SHARING_VIOLATION || errorCode == ERROR_LOCK_VIOLATION; 
} 

internal static bool CanReadFile(string filePath) 
{ 
    //Try-Catch so we dont crash the program and can check the exception 
    try { 
     //The "using" is important because FileStream implements IDisposable and 
     //"using" will avoid a heap exhaustion situation when too many handles 
     //are left undisposed. 
     using (FileStream fileStream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) { 
      if (fileStream != null) fileStream.Close(); //This line is me being overly cautious, fileStream will never be null unless an exception occurs... and I know the "using" does it but its helpful to be explicit - especially when we encounter errors - at least for me anyway! 
     } 
    } 
    catch (IOException ex) { 
     //THE FUNKY MAGIC - TO SEE IF THIS FILE REALLY IS LOCKED!!! 
     if (IsFileLocked(ex)) { 
      // do something, eg File.Copy or present the user with a MsgBox - I do not recommend Killing the process that is locking the file 
      return false; 
     } 
    } 
    finally 
    { } 
    return true; 
} 
} 

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

public static byte[] ReadFileBytes(string filePath) 
{ 
    byte[] buffer = null; 
    try 
    { 
     using (FileStream fileStream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) 
     { 
      int length = (int)fileStream.Length; // get file length 
      buffer = new byte[length];   // create buffer 
      int count;       // actual number of bytes read 
      int sum = 0;       // total number of bytes read 

      // read until Read method returns 0 (end of the stream has been reached) 
      while ((count = fileStream.Read(buffer, sum, length - sum)) > 0) 
       sum += count; // sum is a buffer offset for next reading 

      fileStream.Close(); //This is not needed, just me being paranoid and explicitly releasing resources ASAP 
     } 
    } 
    catch (IOException ex) 
    { 
     //THE FUNKY MAGIC - TO SEE IF THIS FILE REALLY IS LOCKED!!! 
     if (IsFileLocked(ex)) 
     { 
      // do something? 
     } 
    } 
    catch (Exception ex) 
    { 
    } 
    finally 
    { 
    } 
    return buffer; 
} 

public static string ReadFileTextWithEncoding(string filePath) 
{ 
    string fileContents = string.Empty; 
    byte[] buffer; 
    try 
    { 
     using (FileStream fileStream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) 
     { 
      int length = (int)fileStream.Length; // get file length 
      buffer = new byte[length];   // create buffer 
      int count;       // actual number of bytes read 
      int sum = 0;       // total number of bytes read 

      // read until Read method returns 0 (end of the stream has been reached) 
      while ((count = fileStream.Read(buffer, sum, length - sum)) > 0) 
      { 
       sum += count; // sum is a buffer offset for next reading 
      } 

      fileStream.Close(); //Again - this is not needed, just me being paranoid and explicitly releasing resources ASAP 

      //Depending on the encoding you wish to use - I'll leave that up to you 
      fileContents = System.Text.Encoding.Default.GetString(buffer); 
     } 
    } 
    catch (IOException ex) 
    { 
     //THE FUNKY MAGIC - TO SEE IF THIS FILE REALLY IS LOCKED!!! 
     if (IsFileLocked(ex)) 
     { 
      // do something? 
     } 
    } 
    catch (Exception ex) 
    { 
    } 
    finally 
    { }  
    return fileContents; 
} 

public static string ReadFileTextNoEncoding(string filePath) 
{ 
    string fileContents = string.Empty; 
    byte[] buffer; 
    try 
    { 
     using (FileStream fileStream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) 
     { 
      int length = (int)fileStream.Length; // get file length 
      buffer = new byte[length];   // create buffer 
      int count;       // actual number of bytes read 
      int sum = 0;       // total number of bytes read 

      // read until Read method returns 0 (end of the stream has been reached) 
      while ((count = fileStream.Read(buffer, sum, length - sum)) > 0) 
      { 
       sum += count; // sum is a buffer offset for next reading 
      } 

      fileStream.Close(); //Again - this is not needed, just me being paranoid and explicitly releasing resources ASAP 

      char[] chars = new char[buffer.Length/sizeof(char) + 1]; 
      System.Buffer.BlockCopy(buffer, 0, chars, 0, buffer.Length); 
      fileContents = new string(chars); 
     } 
    } 
    catch (IOException ex) 
    { 
     //THE FUNKY MAGIC - TO SEE IF THIS FILE REALLY IS LOCKED!!! 
     if (IsFileLocked(ex)) 
     { 
      // do something? 
     } 
    } 
    catch (Exception ex) 
    { 
    } 
    finally 
    { 
    } 

    return fileContents; 
} 

Попробуйте себя:

byte[] output1 = Helper.ReadFileBytes(@"c:\temp\test.txt"); 
string output2 = Helper.ReadFileTextWithEncoding(@"c:\temp\test.txt"); 
string output3 = Helper.ReadFileTextNoEncoding(@"c:\temp\test.txt"); 
+8

Я бы поднял голову, если там было не так много «магических чисел» там http://en.wikipedia.org/wiki/Magic_number_(programming) – Kris

+7

@ Kris meh can not you read bit shifts, lol –

+2

Я имел в виду errorCode, а не сдвиги бит. хотя теперь вы упоминаете об этом ... – Kris

1

В моем опыте, вы обычно хотите это сделать, то «защитить» свои файлы, чтобы сделать что-то фантазии, а затем использовать " защищенных "файлов. Если у вас есть только один файл, который вы хотите использовать таким образом, вы можете использовать трюк, который объясняется в ответ Джереми Томпсоном. Однако, если вы попытаетесь сделать это на большом количестве файлов (скажем, например, когда вы пишете установщик), вам будет очень больно.

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

Обратите внимание, что вы должны знать об очевидных способах его использования. В конце концов, файлы не будут заблокированы. Кроме того, имейте в виду, что есть другие причины, которые могут привести к ошибке вашей операции Move. Очевидно, что правильная обработка ошибок (MSDN) может помочь здесь.

var originalFolder = @"c:\myHugeCollectionOfFiles"; // your folder name here 
var someFolder = Path.Combine(originalFolder, "..", Guid.NewGuid().ToString("N")); 

try 
{ 
    Directory.Move(originalFolder, someFolder); 

    // Use files 
} 
catch // TODO: proper exception handling 
{ 
    // Inform user, take action 
} 
finally 
{ 
    Directory.Move(someFolder, originalFolder); 
} 

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

+0

Привет, Поскольку порядок ответов меняется, вы можете уточнить, какую должность ** выше ** вы имеете в виду для читателей этого популярного QA. Благодарю. –

+1

@JeremyThompson Вы правы, спасибо, я отредактирую сообщение. Я бы воспользовался этим решением, главным образом из-за правильного использования 'FileShare' и проверки блокировки. – atlaste

3

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

Используйте функцию ниже, например

TimeoutFileAction(() => { System.IO.File.etc...; return null; }); 

многоразовый метод, который раз через 2 секунды

private T TimeoutFileAction<T>(Func<T> func) 
{ 
    var started = DateTime.UtcNow; 
    while ((DateTime.UtcNow - started).TotalMilliseconds < 2000) 
    { 
     try 
     { 
      return func();      
     } 
     catch (System.IO.IOException exception) 
     { 
      //ignore, or log somewhere if you want to 
     } 
    } 
    return default(T); 
} 
2

Принятые ответы выше страдают вопрос, где, если файл был открыт для записи с FileShare.Read или если файл имеет атрибут «Только для чтения», код не будет работать.Это модифицированное решение работает наиболее надежно, с двумя вещами, чтобы иметь в виду (как верно для принятого решения также):

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

Сохраняя выше в виду, это проверяет, является ли файл либо заблокирован для записи или заблокирован, чтобы предотвратить чтение:

public static bool FileLocked(string FileName) 
{ 
    FileStream fs = null; 

    try 
    { 
     // NOTE: This doesn't handle situations where file is opened for writing by another process but put into write shared mode, it will not throw an exception and won't show it as write locked 
     fs = File.Open(FileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None); // If we can't open file for reading and writing then it's locked by another process for writing 
    } 
    catch (UnauthorizedAccessException) // https://msdn.microsoft.com/en-us/library/y973b725(v=vs.110).aspx 
    { 
     // This is because the file is Read-Only and we tried to open in ReadWrite mode, now try to open in Read only mode 
     try 
     { 
      fs = File.Open(FileName, FileMode.Open, FileAccess.Read, FileShare.None); 
     } 
     catch (Exception) 
     { 
      return true; // This file has been locked, we can't even open it to read 
     } 
    } 
    catch (Exception) 
    { 
     return true; // This file has been locked 
    } 
    finally 
    { 
     if (fs != null) 
      fs.Close(); 
    } 
    return false; 
} 
+0

По-прежнему имеет ту же проблему, что и принятый ответ - он сообщает только, был ли файл заблокирован другим процессом * в определенный момент времени *, что не является полезной информацией. К моменту возврата функции результат может уже быть устаревшим! –

+1

Это правда, можно только проверить в любой момент времени (или подписаться на события), преимущество этого подхода в отношении принятого решения состоит в том, что он может проверять атрибут только для чтения и блокировку записи, а не возвращать ложноположительные , – rboy

5

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

private async Task<Stream> GetStreamAsync() 
{ 
    try 
    { 
     return new FileStream("sample.mp3", FileMode.Open, FileAccess.Write); 
    } 
    catch (IOException) 
    { 
     await Task.Delay(TimeSpan.FromSeconds(1)); 
     return await GetStreamAsync(); 
    } 
} 

Вы можете использовать этот поток, как обычно:

using (var stream = await FileStreamGetter.GetStreamAsync()) 
{ 
    Console.WriteLine(stream.Length); 
} 
+0

Сколько секунд до переполнения стека из рекурсии в 'GetStreamAsync()'? –

+0

@ CADbloke, вы подняли очень хороший момент. На самом деле у моего образца может быть исключение переполнения стека, если файл недоступен в течение длительного времени. В связи с этим ответом https://stackoverflow.com/questions/4513438/c-sharp-recursion-depth-how-deep-can-you-go, это может вызвать исключение через 5 часов. –

+0

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

2

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

public static bool IsFileLocked(string file) 
    { 
     try 
     { 
      using (var stream = File.OpenRead(file)) 
       return false; 
     } 
     catch (IOException) 
     { 
      return true; 
     }   
    } 

Однако я думаю, что это является более надежной, чтобы сделать это следующим образом:

public static void TryToDoWithFileStream(string file, Action<FileStream> action, 
     int count, int msecTimeOut) 
    { 
     FileStream stream = null; 
     for (var i = 0; i < count; ++i) 
     { 
      try 
      { 
       stream = File.OpenRead(file); 
       break; 
      } 
      catch (IOException) 
      { 
       Thread.Sleep(msecTimeOut); 
      } 
     } 
     action(stream); 
    } 
-1

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

Вы можете установить его с NuGet: Install-Package Xabe.FileLock

Если вы хотите получить больше информации о нем проверить https://github.com/tomaszzmuda/Xabe.FileLock

ILock fileLock = new FileLock(file); 
if(fileLock.Acquire(TimeSpan.FromSeconds(15), true)) 
{ 
    using(fileLock) 
    { 
     // file operations here 
    } 
} 

метод fileLock.Acquire возвращает истину, только если можно заблокировать файл эксклюзив для этого объекта. Но приложение, загружающее файл, должно делать это и в блокировке файлов. Если объект недоступен, метод возвращает false.

+0

Пожалуйста, не просто отправляйте какой-либо инструмент или библиотеку в качестве ответа. По крайней мере, продемонстрируйте [как он решает проблему] (http://meta.stackoverflow.com/a/251605) в самом ответе. – paper1111

+0

Добавлена ​​демо :) Извините @ paper1111 –

+1

Требуется, чтобы все процессы, которые используют файл, сотрудничали. Маловероятно, чтобы быть применимым к исходной проблеме OPs. –

Смежные вопросы