2012-05-11 4 views
-1

У меня есть приложение формы, которое выполняет симуляцию и постоянно читает/записывает двоичный файл. Все работает нормально, если вы позволите этому пробежаться. Однако, если форма закрыта/симуляция отменена, поток файлов не закрывается должным образом, оставляя файл заблокированным. Есть ли способ убедиться, что все потоки закрыты? Я попытался следующие - но это не имеет никакого эффекта ... Большое спасибо заранее, TBinaryReader или Writer.Close() не закрывается должным образом C#

 public BinaryWriter BinWrite; 
     public BinaryReader BinRead; 

     public BinaryWriter EnvBinWrite; 
     public BinaryReader EnvBinRead;  

public void theForm_FormClosing(object sender, FormClosingEventArgs e) 
     { 

      //Close all binary file reader/writers -- crashes if it cannot overwrite files 
      foreach (Building B in AllBldgs) 
      { 
       try 
       { 
        EnvBinRead.Close(); 
       } 
       catch 
       { continue; } 
       try 
       { 
        EnvBinWrite.Close(); 
       } 
       catch 
       { continue; } 
       try 
       { 
        BinRead.Close(); 
       } 
       catch 
       { continue; } 

       try 
       { 
        BinWrite.Close(); 
       } 
       catch 
       { continue; } 
      } 
     } 
+0

Есть ли исключения? – CodeCaster

+0

не то, что я знаю .. – timkado

+2

Нет, потому что вы их съедаете. Удалите блоки try..catch и проверьте, не произошло ли это. – CodeCaster

ответ

7

Вы уверены, что вы знаете, что continue ключевое слово для? Обратите внимание, что это продолжается следующим циклом , а не следующим блок кода. Поэтому, если возникает исключение, закрывающее EnvBinRead, вы должны: не войти в блок, чтобы закрыть EnvBinWrite, но идите по следующему объекту с AllBldgs.

Кушать все исключения и до сих пор пытается закрыть все бинарные писатель, вы бы написать:

foreach (Building B in AllBldgs) 
{ 
    try 
    { 
     EnvBinRead.Close(); 
    } 
    catch (Exception exp) 
    { 
     Console.WriteLine("Closing EnvBinRead failed!" + exp.ToString()); 
    } 

    try 
    { 
     EnvBinWrite.Close(); 
    } 
    catch (Exception exp) 
    { 
     Console.WriteLine("Closing EnvBinWrite failed!" + exp.ToString()); 
    } 

    try 
    { 
     BinRead.Close(); 
    } 
    catch (Exception exp) 
    { 
     Console.WriteLine("Closing BinRead failed!" + exp.ToString()); 
    } 

    try 
    { 
     BinWrite.Close(); 
    } 
    catch (Exception exp) 
    { 
     Console.WriteLine("Closing BinWrite failed!" + exp.ToString()); 
    } 
} 

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

+0

+1, так как это, вероятно, является источником проблемы. Тем не менее, я бы посоветовал, что употребление исключений - это плохо, и что-то вроде 'if (BinRead! = Null) BinRead.Close();' было бы предпочтительнее, если бы «BinRead» мог быть неинициализирован. – Heinzi

+0

Да, я поддерживаю это. –

+0

Спасибо! Как я могу проверить, произошло ли исключение? – timkado

2

Вы должны позвонить в распоряжение, чтобы закрыть BinaryReader и Writer.

Объяснение:

StreamReader, StreamWriter, BinaryReader and BinaryWriter все близко/утилизировать их основные потоки при вызове Dispose на них. Они не избавляются от потока, если читатель/писатель просто собирает мусор - вы всегда должны распоряжаться читателем/писателем, предпочтительно с заявлением using. (На самом деле, ни один из этих классов не имеет финализаторов, и не должен их иметь.)

Лично я предпочитаю использовать инструкцию для потока. Вы можете гнездо, используя операторы без скобок довольно аккуратно:

using (Stream stream = ...) 
using (StreamReader reader = new StreamReader(stream, Encoding.Whatever)) 
{ 
} 

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

1

Всегда полезно использовать блок для потоков, закрывая их сразу же после использования.

+1

На самом деле вы действительно не знаете. Хотя использование 'use' рекомендуется, когда вы действительно хотите закрыть поток сразу после чтения/записи с/на него, могут быть сценарии, в которых поток должен быть открыт по всему жизненному циклу приложения. В этом случае «использование» не может использоваться вообще. –