Закрытие потока после исключения

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

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

Как закрыть поток после этого исключения? Если я поставлю stream.Close() либо в catch, либо в finally, он жалуется на попытку доступа к неназначенной локальной переменной. Кажется плохой практикой просто открывать случайный файл, который, как я знаю, там есть. Есть ли способ открыть поток таким образом, чтобы он был похож на пустой конструктор, чтобы он выглядел так, как будто он назначен?

Спасибо

SavedEventSet sES;
OpenFileDialog oFD = new OpenFileDialog();
Stream stream;
BinaryFormatter bF;

try
{
    oFD.InitialDirectory = this.path;
    oFD.Title = "Open Event Saved File.";
    oFD.ShowDialog();

    if(oFD.FileName.Contains(".sav"))
    {
        stream = File.Open(oFD.FileName, FileMode.Open);
        bF = new BinaryFormatter();

        sES = (SavedEventSet)bF.Deserialize(stream);
        stream.Close();

    }
}
catch (Exception ex)
{
    stream.Close();
    /*handle Exception*/
}

person EatATaco    schedule 21.01.2010    source источник


Ответы (3)


Вы можете использовать блок using, который автоматически закрыть поток, даже если есть исключение:

using(Stream stream = File.Open(oFD.FileName, FileMode.Open))
{
    bF = new BinaryFormatter();

    sES = (SavedEventSet)bF.Deserialize(stream);
}
person ShZ    schedule 21.01.2010
comment
+1 за using(). За кулисами он компилируется в блок try/catch и гарантирует вызов Dispose() — его можно использовать во всех реализациях IDisposable. - person STW; 22.01.2010
comment
Я согласен, это именно то, для чего предназначен блок «использование». - person auujay; 22.01.2010
comment
Спасибо :) Я даже не знал об использовании блока. - person EatATaco; 22.01.2010

Установите для потока значение null перед блоком try.

В вашем улове проверьте, не является ли поток нулевым, если нет, то закройте поток.

  SavedEventSet sES;
  OpenFileDialog oFD = new OpenFileDialog();
  Stream stream = null;
  BinaryFormatter bF;

  try
  {
    oFD.InitialDirectory = this.path;
    oFD.Title = "Open Event Saved File.";
    oFD.ShowDialog();

    if (oFD.FileName.Contains(".sav"))
    {
      stream = File.Open(oFD.FileName, FileMode.Open);
      bF = new BinaryFormatter();

      sES = (SavedEventSet)bF.Deserialize(stream);
      stream.Close();

    }
  }
  catch (Exception ex)
  {
    if (stream != null)
      stream.Close();
    /*handle Exception*/
  }
person Daniel    schedule 21.01.2010
comment
Я не понимаю, почему это не просто нуль для начала. Но это сработало, спасибо :) - person EatATaco; 22.01.2010
comment
Я думаю, что значение по умолчанию равно null, т.е. вы можете явно назначить null только во избежание возможных предупреждений компилятора. - person i486; 27.10.2014

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

try
{
  oFD.InitialDirectory = this.path;
  oFD.Title = "Open Event Saved File.";
  oFD.ShowDialog();

  if(oFD.FileName.Contains(".sav"))
  {
    stream = File.Open(oFD.FileName, FileMode.Open);
    bF = new BinaryFormatter();

    sES = (SavedEventSet)bF.Deserialize(stream);
  }
}
catch (Exception ex)
{
  /*handle Exception*/
}
finally
{
  if (stream != null)
    stream.Close();
}
person Oded    schedule 21.01.2010
comment
Это на самом деле не работает. Я получаю ту же проблему с неназначенной локальной переменной. - person EatATaco; 22.01.2010
comment
Я бы тоже предпочел этот вариант, но для того, чтобы он работал, вам нужно, чтобы поток был создан вне блока try/catch/finally. - person Wagner Silveira; 22.01.2010
comment
@Wagner Silveira - он создал его за пределами блока. - person Oded; 22.01.2010
comment
Извините, я имел в виду создать и инициализировать его... The Stream stream = null; строка, которая отсутствовала в его исходном коде. - person Wagner Silveira; 25.01.2010