Удаление / создание файлов выдает System.UnauthorizedAccessException после большого количества итераций - PullRequest
0 голосов
/ 05 февраля 2019

При тестировании некоторых вещей о записи / создании / удалении файлов я создал следующую программу, которая удаляет и создает файл в цикле n раз.

static string path = @"C:\Users\Remy\Desktop\Testing";
static readonly int sampleSize = 10000; // Amount of iterations the methods will be run for.

static byte[] sourceFile;

static void Main(string[] args)
{
    using (FileStream fs = new FileStream(path + @"\SourceFile.txt", FileMode.Open, FileAccess.Read))
    {
        sourceFile = new byte[fs.Length];
        fs.Read(sourceFile, 0, sourceFile.Length);
    }

    string filePath = path + @"\Destination.txt";
    for (int i = 0; i < sampleSize; i++)
    {
        if (File.Exists(filePath))
        {
            File.SetAttributes(filePath, FileAttributes.Normal);
            File.Delete(filePath);//Error sometimes throws here.
        }

        using (FileStream file = File.OpenWrite(filePath))
        {
            file.Write(sourceFile, 0, sourceFile.Length);
        }
    }

    Console.ReadLine();
}

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

Однако, когда я увеличиваю количество итераций до 10000/100000, возникают проблемы, когда в редких случаях (примерно в 0,03% случаев) он выбрасывает System.UnauthorizedAccessException при using (FileStream file = File.OpenWrite(filePath)), в то же время успешно пропуская остальные 99,97%время.Когда выдается ошибка, файл не создается.

Это происходит как в VS (как администратор), использующей Debug / release, так и в сборке .exe, запускается от имени администратора.

При поискевокруг этой проблемы я нашел следующие ответы относительно Unauth... исключений.

  • этот ответ предлагает установить атрибуты, но, как видно из моего примера, я уже это делаю.
  • это и некоторые другие ответы предлагают запустить приложение с правами администратора.Что я уже делаю aswel.

Я также добавил разрешения родительской папки, чтобы разрешить full control до Everyone для всех файлов и подпапок.

Сначала я подумал, что, возможно, файл, который я создавал, был недостаточно большим (в настоящее время записывает 976 КБ случайных данных), и по какой-то причине программа перебирала создание / удаление быстрее, чем могла справиться ОС / жесткий диск.Но то же самое происходит при увеличении размера файла

Я проверил его на 3 компьютерах, и это произошло на всех них.

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

Примечание: я не ищу способ обработать исключение.Я могу справиться с этим.Что я ищу по причине почему происходит такое странное поведение, и если возможно предотвращает это вместо лечения это


Среда

Диск, на который я пишу, - это Crucial MX300 SSD, использующий sata 3 без RAID.16 ГБ оперативной памяти.ОС Windows 10 (pro) 64-разрядная.Во время работы программы система работает максимально бездействующей.

Консольное приложение предназначено для сборки .NET Framework 4.6.1 с использованием Visual Studio 2017 с параметром Release Any CPU.


Дополнительные действия, которые я пробовал в соответствии с комментариями:

Я попытался добавить Thread.Sleep после создания и удаления, чтобы убедиться, что Windows получает возможность очистить файловый кеш.Это по-прежнему выдает исключение, но на этот раз оно выдает исключение File.Delete(filePath);.

Выключение Защитника Windows и т. Д. Также дает результат возникновения ошибки File.Delete(filePath) вместо using(FIleStream....) aswel.

Запись в файл, используя вместо этого следующее:

using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Write, FileShare.None)) 
{ 
    file.Write(sourceFile, 0, sourceFile.Length); file.Flush(flushToDisk: true); 
}

также выдает то же исключение, которое выдается

1 Ответ

0 голосов
/ 05 февраля 2019

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

public IList<string> ReadLineByLineFromFile( string filePath )
{
    const int numberOfRetries = 3;
    const int delayOnRetry = 500;

    bool success = false;
    List<string> logs = null;

    for ( int i = 0; i <= numberOfRetries && success == false; i++ )
    {
        try
        {
            logs = new List<string>();

            const Int32 bufferSize = 128;
            using ( var fileStream = File.Open( filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ) )
            using ( var streamReader = new StreamReader( fileStream, Encoding.UTF8, true, bufferSize ) )
            {
                string line;

                while ( ( line = streamReader.ReadLine() ) != null )
                {
                    logs.Add( line );
                }
            }

            success = true;
        }
        catch ( IOException ex ) when ( i < numberOfRetries )
        {
            Local.Instance().Logger.Warn( ex, "Retrying reading logs from file path {0}, retry count {1} with dealy {2} ms.", filePath, i + 1,
                delayOnRetry );

            System.Threading.Thread.Sleep( delayOnRetry );
        }
    }

    GC.Collect();

    return logs;
}
...