Программа Winforms должна сохранить некоторую информацию о времени выполнения в файл XML. Файл иногда может быть размером в несколько сотен килобайт. Во время бета-тестирования мы обнаружили, что некоторые пользователи без колебаний прерывали процессы, казалось бы, наугад, что иногда приводило к тому, что файл наполовину записывался и поэтому был поврежден.
Таким образом, мы изменили алгоритм для сохранения во временном файле, а затем для удаления реального файла и выполнения перемещения.
Наш код в настоящее время выглядит следующим образом ..
private void Save()
{
XmlTextWriter streamWriter = null;
try
{
streamWriter = new XmlTextWriter(xmlTempFilePath, System.Text.Encoding.UTF8);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(MyCollection));
xmlSerializer.Serialize(streamWriter, myCollection);
if (streamWriter != null)
streamWriter.Close();
// Delete the original file
System.IO.File.Delete(xmlFilePath);
// Do a move over the top of the original file
System.IO.File.Move(xmlTempFilePath, xmlFilePath);
}
catch (System.Exception ex)
{
throw new InvalidOperationException("Could not save the xml file.", ex);
}
finally
{
if (streamWriter != null)
streamWriter.Close();
}
}
Это работает в лаборатории и на производстве почти все время. Программа работает на 12 компьютерах, и этот код вызывается в среднем один раз каждые 5 минут. Примерно один или два раза в день мы получаем это исключение:
System.InvalidOperationException:
Could not save the xml file.
---> System.IO.IOException: Cannot create a file when that file already exists.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.__Error.WinIOError()
at System.IO.File.Move(String sourceFileName, String destFileName)
at MyApp.MyNamespace.InternalSave()
Это похоже на то, как если бы удаление фактически не выдавалось на жесткий диск перед выполнением перемещения.
Это происходит на машинах Win7.
Пара вопросов: существует ли какая-то концепция Flush()
, которую можно использовать для всей дисковой операционной системы? Это ошибка с моим кодом, .net, ОС или чем-то еще? Должен ли я положить в Thread.Sleep(x)
? Может мне стоит сделать File.Copy(src, dest, true)
? Должен ли я написать следующий код? (Но это выглядит довольно глупо.)
while (System.IO.File.Exists(xmlFilePath))
{
System.IO.File.Delete(xmlFilePath);
}
// Do a move over the top of the main file
bool done = false;
while (!done)
{
try
{
System.IO.File.Move(xmlTempFilePath, xmlFilePath);
done = true;
}
catch (System.IO.IOException)
{
// let it loop
}
}
Кто-нибудь видел это раньше?