Исключение, за исключением случаев, когда выполняется после точки останова - PullRequest
4 голосов
/ 24 июня 2019

Я сталкиваюсь с каким-то странным поведением при попытке удалить файл. Ниже приведен пример быстрого кода:

if (File.Exists(filePath))
{
    File.Delete(filePath);
}

При попытке удалить файл выдается странное поведение System.IO.IOException:

System.IO.IOException
HResult = 0x80070020
Сообщение = Процесс не может получить доступ к файлу 'C: \ ProgramData \ Path \ To \ File.sqlite', поскольку он используется другим процессом.
Источник = mscorlib

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

Это кажется довольно нормальной проблемой. Странное поведение начинается при добавлении точек останова в код. Например, если мы добавим оператор Console.WriteLine выше, разбить этот оператор, а затем продолжить:

<x> Console.WriteLine("Break");
    if (File.Exists(filePath))
    {
        File.Delete(filePath);
    }

Нет исключений.

Если мы добавим точку останова следующим образом:

    Console.WriteLine("Break");
    if (File.Exists(filePath))
    {
<x>     File.Delete(filePath);
    }

или как это:

    Console.WriteLine("Break");
<x> if (File.Exists(filePath))
    {
        File.Delete(filePath);
    }

Исключение выдается.

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

Edit: некоторые заметки, которые я забыл добавить, мы можем воспроизвести это поведение на нескольких разных машинах. Добавление Thread.Sleep() не меняет поведение.

Любое понимание очень ценится!

1 Ответ

1 голос
/ 25 июня 2019

Через несколько часов, некоторые Google и много волос вытащил, я выяснил причину этого поведения.

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

Все наши операторы SQLite заключены в использование, обеспечивая вызов Dispose (). По какой-то причине не похоже, что сборщик мусора был запущен, а некоторые блокировки файлов остались. Когда мы добавили точки останова, похоже, что за кулисами что-то запускалось.

Добавление следующего было достаточно, чтобы все заработало, как мы ожидали:

GC.WaitForPendingFinalizers();
...