#c# #exception #streamwriter #file-in-use
#c# #исключение #streamwriter #используемый файл
Вопрос:
Я получаю сообщение об ошибке:
The process cannot access the file
'C:AMR_VOYANT_TESTINGPWM_TESTERUUT_LOGSTEST_LOG_PWM_10245_UUT_SN_10.TXT'
because it is being used by another process.
Моя программа сбрасывает, закрывает и удаляет файл журнала. Позже моя программа пытается открыть файл, чтобы добавить больше данных. Это второе открытие вызывает вышеупомянутое исключение.
Process Explorer
не показывает дескриптор файла, во время выполнения либо напрямую обращается к двоичному файлу, либо выполняется в режиме отладки с MS Visual C # Express 2008.
Никакие другие процессы не должны использовать этот файл, поскольку это оригинальный файл, созданный моим приложением.
Некоторые решения в Stack Overflow предполагают реализацию using
инструкции, но это неосуществимо, поскольку запись данных не происходит в простой или короткой составной инструкции. Класс ведения журнала использует делегат записи для записи данных в файл.
Согласно другим решениям в Stack Overflow, в for
цикле файл может не быть закрыт до следующей итерации, на которой файл открывается. Я подождал более 10 секунд, прежде чем снова открыть файл, но безрезультатно (то же исключение).
Вот пример кода:
public void
close()
{
get_log_file().WriteLine("");
get_log_file().Flush();
get_log_file().Close();
get_log_file().Dispose();
m_log_file = null;
return;
}
private StreamWriter
get_log_file()
{
if (m_log_file == null)
{
bool successful = false;
int retries_remaining = 5;
// do
// {
// try
// {
// m_log_file = new StreamWriter(m_filename, true);
m_log_file = new StreamWriter(new FileStream(m_filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None));
// }
// catch (IOException)
// {
// --retries_remaining;
// System.Threading.Thread.Sleep(250); // Units are in milliseconds;
// }
// } while (!successful amp;amp; (retries_remaining >= 0));
}
return m_log_file;
}
private System.IO.StreamWriter m_log_file = null;
private string m_filename;
Поскольку мне нужно уложиться в крайний срок, я ищу решения этой проблемы. Некоторые из моих идей:
- Держите файл открытым; не открывайте и не закрывайте во время тестовых запусков.
- Выводите пользователю сообщение «ожидание файла» во время опроса файла (чтобы узнать, когда его можно будет открыть снова)
- Написание неуправляемой библиотеки C или C для обработки файлового ввода-вывода (поскольку неуправляемые C и C не используют .NET framework).
- Учимся определять .NET framework, чтобы поторопиться и закрыть файл.
Я использую MS Visual C # 2008 Express на Windows 7, 64-разрядная архитектура.
Комментарии:
1. Почему вы пишете свой собственный журнал регистрации? Можете ли вы использовать фреймворк, такой как log4net, для записи этого журнала? Потому что я могу быстро дать вам этот ответ.
2. можете ли вы изменить файловый ресурс. Нет для общего доступа к файлам. Читать и переписывать ?
3. Если не используется ‘using’, вы должны всегда использовать try-finally, чтобы гарантировать, что Dispose всегда вызывается. Первый тест, который может завершиться неудачей между сбросом и утилизацией?
4. Если верить вашему фрагменту, у вас есть метод с именем «close», который открывает файл журнала. Не имеет особого смысла, ваш код просто не вызывает close() делает . Реальный код, вероятно, также не является безопасным для исключений. Исключение NullReferenceException — это еще один режим сбоя, который вы допускаете, не проверяя возвращаемое значение get_log_file() .
5. Вы уверены , что ProcExp не показывает никаких дескрипторов файла, открытого при получении ошибки? Вы должны опубликовать минимальный рабочий образец, который воспроизводит проблему.
Ответ №1:
- Если вы хотите сделать это правильно, вам придется потратить некоторое время. Или
- Используйте систему отслеживания или протоколирования.
- Я предполагаю, что вы выполняете отладку с помощью процесса хостинга Visual Studio. Попробуйте отключить его и проверьте, исчезнет ли проблема с блокировкой файла.
Отключите флажок
Project - Properties - Debug - x Enable Visual Studio hosting process
Также может быть, что вы выполняете трассировку в одном из ваших финализаторов во время завершения работы приложения, когда StreaWriter уже был закрыт. Вы можете обойти это, используя критический финализатор
С уважением, Алоис Краус
Ответ №2:
То, что, я надеюсь, предложит вам быстрое решение, — это заменить FileMode.OpenorCreate
на FileMode.Append
;
Как отмечают другие, существует множество других вариантов ведения журнала, но я полагаю, что это может предложить вам быстрый путь вперед с того места, где вы стоите, вместо того, чтобы идти назад, чтобы продвинуться вперед.
Мне кажется, что ваш код представляет собой фрагмент класса, который возвращает streamwriter в вызывающий контекст. Я бы заставил ваш класс реализовать IDisposable, изменив ваше close на Dispose (для реализации IDisposable), а затем заставил вашего потребителя обернуть вызов в using(yourLogClass logger = new yourLogClass()) … и т.д. чтобы гарантировать, что close вызывается при каждом использовании.
Ответ №3:
Код, вызывающий методы в этом классе, не вызывает ваш метод close() после вызова метода open. Основываясь на коде, который вы опубликовали, я предполагаю, что существует отдельный открытый метод. Если этот метод вызывается более одного раза, то вы получите описываемое вами исключение. Опубликованный вами код не имеет проблем, которые могли бы вызвать получаемое вами исключение. Если вы вызовете Flush() перед вызовом Close (), это принудительно выполнит запись на диск, чтобы не было задержки при вызове Close () Я забивал файлы, открывая и закрывая их сотни раз в течение секунды или двух, и никогда не сталкивался с этой проблемой.
Обновление: если ваш код вызвал исключение во время его отладки, у VS все еще есть открытый дескриптор этого файла. Он будет продолжать выдавать это исключение, даже если вы исправили свой код. Обычно я просто закрываю и перезапускаю VS, чтобы не перепутать настройки моего проекта и случайно не проверить их в системе управления версиями.
Комментарии:
1. кроме того, этот класс удерживает неуправляемый ресурс, количество которого на компьютере ограничено. Вам нужно реализовать IDisposable и финализатор. msdn.microsoft.com/en-us/library/b1yfkh5e (v=VS.100).aspx
Ответ №4:
Я решил эту проблему, оставив файл открытым, что избавило от необходимости каждый раз открывать его заново.