Есть ли способ проверить, используется ли файл?

746

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

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

  • 24
    Хорошо, вы можете проверить это, изучив все открытые маркеры в системе. Однако, поскольку Windows является многозадачной операционной системой, есть вероятность, что сразу после запуска кода, чтобы определить, открыт ли файл, и вы считаете, что это не так, код процесса начинает использовать этот файл, а затем, когда вы пытаетесь используйте его, вы получите ошибку. Но в проверке нет ничего плохого; только не думайте, что он не используется, когда он вам действительно нужен.
  • 3
    Но только для этой конкретной проблемы; Я бы порекомендовал не проверять файловые дескрипторы и просто попробовать какое-то заданное количество раз, скажем 3-5, прежде чем потерпеть неудачу.
Показать ещё 8 комментариев
Теги:
file
file-io
file-locking

20 ответов

481
Лучший ответ

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

ORIGINAL: Я использовал этот код в течение последних нескольких лет, и у меня не было никаких проблем с ним.

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

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;
}
  • 57
    Это отличное решение, но у меня есть один комментарий - вы можете не захотеть открывать файл с режимом доступа FileAccess.Read, так как ReadWrite всегда завершится ошибкой, если файл будет доступен только для чтения.
  • 6
    Хороший ответ, но проблема в том, что файл может фактически не существовать, что вызовет исключение FileNotFound - это IOException. Блок перехвата IOException поймает это, и результат метода интерпретирует это как заблокированный файл, когда на самом деле файл фактически не существует - это может привести к трудным для диагностики ошибкам. Сложно с точки зрения API - возможно, API должен быть GetFileState, который возвращает перечисление: Locked, NotFound, KnockYourselfOut. :) Конечно, может быть создано UnauthorizedAccessException, которое не является IOException ...
Показать ещё 33 комментария
543

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

Лучше всего попробовать try 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.
}
  • 110
    +1. Не существует 100% безопасного способа «узнать, используется ли файл», потому что миллисекунды после того, как вы выполните проверку, файл может больше не использоваться, или наоборот. Вместо этого вы просто открываете файл и используете его, если нет исключений.
  • 8
    Жаль, что .NET не поддерживает CAS. Что-то вроде TryOpenFile (Ref FileHandle), которое возвращает успех / неудачу. Всегда должен быть обходной путь, а не полагаться только на обработку исключений. Интересно, как это делает Microsoft Office.
Показать ещё 14 комментариев
81

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

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
    Я бы поддержал, если бы там не было так много "магических чисел" en.wikipedia.org/wiki/Magic_number_(programming)
  • 8
    @ Крис, ты не можешь читать сдвиги, лол
Показать ещё 10 комментариев
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
}
6

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

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

  • 1
    Использование FileSystemWatcher не помогает, потому что события Created и Changed возникают в начале создания / изменения файла. Даже небольшие файлы требуют больше времени для записи и закрытия операционной системой, чем приложение .NET для запуска через обратный вызов FileSystemEventHandler. Это так печально, но нет другого выбора, кроме как оценить время ожидания перед доступом к файлу или запуститься в циклах исключений ...
  • 0
    FileSystemWatcher не очень хорошо обрабатывает множество изменений одновременно, поэтому будьте осторожны с этим.
Показать ещё 2 комментария
4

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

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);
}
  • 2
    Сколько секунд до переполнения стека из рекурсии в GetStreamAsync() ?
  • 0
    @CADbloke, вы подняли очень хороший вопрос. Действительно, мой образец может иметь исключение переполнения стека, если файл не доступен в течение длительного времени. В связи с этим ответом stackoverflow.com/questions/4513438/… может вызвать исключение через 5 часов.
Показать ещё 5 комментариев
4

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

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

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);
}
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");

Надеюсь, это поможет!

  • 9
    Фактическая проверка, которую вы выполняете, в порядке; помещение его внутрь функции вводит в заблуждение. Вы НЕ хотите использовать такую функцию перед открытием файла. Внутри функции файл открывается, проверяется и закрывается. Затем программист предполагает, что файл все еще в порядке, и пытается открыть его для использования. Это плохо, потому что он может быть использован и заблокирован другим процессом, который был поставлен в очередь для открытия этого файла. Между 1-м разом, когда он был открыт (для проверки), и 2-м разом, когда он был открыт (для использования), ОС могла отложить планирование вашего процесса и запустить другой процесс.
4

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

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

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

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

Вы можете установить его из 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 метод вернет true, только если он может заблокировать файл для этого объекта. Но приложение, загружающее файл, должно делать это и в блокировке файлов. Если объект недоступен, метод возвращает false.

  • 0
    Пожалуйста, не размещайте какой-либо инструмент или библиотеку в качестве ответа. По крайней мере, продемонстрируйте, как это решает проблему в самом ответе.
  • 0
    Добавлена демоверсия :) Извините @ paper1111
Показать ещё 1 комментарий
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);
    }
2

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

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

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

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 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
    это правда, можно проверить только в любой данный момент времени (или подписаться на события), преимущество этого подхода перед принятым решением состоит в том, что он может проверять атрибут только для чтения и блокировку записи и не возвращать ложное срабатывание.
1

Помимо рабочих 3-лайнеров и только для справки: если вы хотите получить полную информацию - в Microsoft Dev Center есть небольшой проект:

https://code.msdn.microsoft.com/windowsapps/How-to-know-the-process-704839f4

Из введения:

Образец кода С#, разработанный в.NET Framework 4.0, поможет выяснить, какой процесс имеет блокировка файла. Функция RmStartSession, которая включена в файл rstrtmgr.dll, была использована для создания сеанса диспетчера перезапуска и в соответствии с результатом возврата создается новый экземпляр объекта Win32Exception. После регистрации ресурсов на сеанс Restart Manager через функцию RmRegisterRescources функция RmGetList вызывается для проверки того, какие приложения используют конкретный файл, перечисляя массив RM_PROCESS_INFO.

Он работает, подключившись к сеансу перезапуска менеджера.

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

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

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 и проверки блокировки.
0

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

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

private static string WriteFileToDisk(byte[] data, string fileName, int version = 0)
{
    try
    {
        var versionExtension = version > 0 ? $"_{version:000}" : string.Empty;
        var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"{fileName}{versionExtension}.pdf");
        using (var writer = new FileStream(filePath, FileMode.Create))
        {
            writer.Write(data, 0, data.Length);
        }
        return filePath;
    }
    catch (IOException)
    {
        return WriteFileToDisk(data, fileName, ++version);
    }
}

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

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

0

если вам нужно избегать блока catch и throw, у вас может быть список строк, который добавляет путь и состояние файла (независимо от того, открыт он или нет). поэтому вы можете проверить, доступен ли путь или нет, из состояния пути, хранящегося в списке строк. Надеюсь, что я предлагаю правильно, если это очень актуально для меня плохо.

-1

Я использую это обходное решение, но у меня есть промежуток времени между тем, когда я проверяю блокировку файла с помощью функции 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?
-3

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

  • 0
    Что делать, если что-то блокирует его сразу после перемещения файла?
  • 0
    @jcolebrand что блокирует? тот, который вы скопировали? Или тот, который вы положили в временный каталог?
Показать ещё 1 комментарий
-7

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

-13

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

Я поставил счетчик, чтобы попытаться 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);
        }
    }

Ещё вопросы

Сообщество Overcoder
Наверх
Меню