Deserialiing problem

J

Jon

Hi,

I'm having a problem with deserialising from a file.

I have two buttons on a Windows form (see simplified example code below). The first serialises an
integer value to a file and the second deserialises the same data from the file.

The first function works fine, but the second causes a runtime exception in the "finally" block.
Stepping through in the debugger, stream is set to something sensible in the try section, but
becomes null as soon as it leaves the try section and enters into the finally section, and calling
Close() on the null causes the exception. Curiously, this exception does not occur in the first
function.

1) For each case, does the stream get closed automatically when if falls out of the try{} scope? If
so, I don't need to have stream.Close() in the finally block. I ask this since when opening a
connection to a database, it is best to explicitly call close, since the GC may not run for a long
time after falling out of scope. I know that closing a stream is not the same as closing a DB
connection, but wondered if similar principles apply?

2) Why does only the second function set stream to null, but not the first function?

I'm using VS 2008 Express, targeting .NET 2.0 on an XP pro PC.


private void btnSaveData_Click(object sender, EventArgs e){
try{
Stream stream = File.Open(@"C:\test.dta", FileMode.Create);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, testInt);
}catch(Exception ex){
// TO DO: add code to recover from exception
}finally{
stream.Close();
}
}

private void btnReadData_Click(object sender, EventArgs e){
try{
Stream stream = File.Open(@"C:\test.dta", FileMode.Open);
BinaryFormatter formatter = new BinaryFormatter();

testInt = (int)formatter.Deserialize(stream);
}catch(Exception ex){
// TO DO: add code to recover from exception
}finally{
stream.Close(); // "stream" is always null here, so get an exception
}
}
 
C

Chris Dunaway

Hi,

I'm having a problem with deserialising from a file.

I have two buttons on a Windows form (see simplified example code below). The first serialises an
integer value to a file and the second deserialises the same data from the file.

The first function works fine, but the second causes a runtime exception in the "finally" block.
Stepping through in the debugger, stream is set to something sensible in the try section, but
becomes null as soon as it leaves the try section and enters into the finally section, and calling
Close() on the null causes the exception. Curiously, this exception does not occur in the first
function.

1) For each case, does the stream get closed automatically when if falls out of the try{} scope? If
so, I don't need to have stream.Close() in the finally block. I ask this since when opening a
connection to a database, it is best to explicitly call close, since the GC may not run for a long
time after falling out of scope. I know that closing a stream is not the same as closing a DB
connection, but wondered if similar principles apply?

2) Why does only the second function set stream to null, but not the first function?

I'm using VS 2008 Express, targeting .NET 2.0 on an XP pro PC.

private void btnSaveData_Click(object sender, EventArgs e){
try{
Stream stream = File.Open(@"C:\test.dta", FileMode.Create);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, testInt);
}catch(Exception ex){
// TO DO: add code to recover from exception
}finally{
stream.Close();
}

}

private void btnReadData_Click(object sender, EventArgs e){
try{
Stream stream = File.Open(@"C:\test.dta", FileMode.Open);
BinaryFormatter formatter = new BinaryFormatter();

testInt = (int)formatter.Deserialize(stream);
}catch(Exception ex){
// TO DO: add code to recover from exception
}finally{
stream.Close(); // "stream" is always null here, so get an exception
}

}

Is that your real code? I can't believe that compiles. Since the
Stream is declared inside the try block, it should not be visible in
the catch or finally blocks. I would expect an exception in both
places.

When using Streams (or anything else that implements IDisposable),
it's often cleaner to use a using block:

using (Stream stream = File.Open(@"C:\test.dta", FileMode.Open)) {
BinaryFormatter formatter = new BinaryFormatter();
testInt = (int)formatter.Deserialize(stream);
}

This ensures that the stream is disposed at the end of the using
block.

Chris
 
I

Ignacio Machin ( .NET/ C# MVP )

Hi,

I'm having a problem with deserialising from a file.

I have two buttons on a Windows form (see simplified example code below).The first serialises an
integer value to a file and the second deserialises the same data from the file.

The first function works fine, but the second causes a runtime exception in the "finally" block.
Stepping through in the debugger, stream is set to something sensible in the try section, but
becomes null as soon as it leaves the try section and enters into the finally section, and calling
Close() on the null causes the exception. Curiously, this exception does not occur in the first
function.

1) For each case, does the stream get closed automatically when if falls out of the try{} scope? If
so, I don't need to have stream.Close() in the finally block. I ask this since when opening a
connection to a database, it is best to explicitly call close, since the GC may not run for a long
time after falling out of scope. I know that closing a stream is not the same as closing a DB
connection, but wondered if similar principles apply?

2) Why does only the second function set stream to null, but not the first function?

I'm using VS 2008 Express, targeting .NET 2.0 on an XP pro PC.

private void btnSaveData_Click(object sender, EventArgs e){
  try{
    Stream stream = File.Open(@"C:\test.dta", FileMode.Create);
    BinaryFormatter formatter = new BinaryFormatter();
    formatter.Serialize(stream, testInt);
  }catch(Exception ex){
    // TO DO: add code to recover from exception
  }finally{
    stream.Close();
  }

}

private void btnReadData_Click(object sender, EventArgs e){
  try{
    Stream stream = File.Open(@"C:\test.dta", FileMode.Open);
    BinaryFormatter formatter = new BinaryFormatter();

    testInt = (int)formatter.Deserialize(stream);
  }catch(Exception ex){
    // TO DO: add code to recover from exception
  }finally{
    stream.Close(); // "stream" is always null here, so get an exception
  }

}

Hi,
As mentioned in other post the Save method cannot compile. apart of
that you should always try to enclose a stream instance (or any class
that implement IDisposable) in a using context:


using (Stream stream = File.Open(@"C:\test.dta", FileMode.Create)){
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, testInt);
}

in this case you do not need to specifically call Close.
 
J

Jon

Hi Chris + Ignacio,

Thanks for your comments.

It's not real code - I've taken my code and removed lots of lines out to simplify the code snippet.

However, both functions in the real code do have the Stream stream = File.Open(...) within the try
and strangely enough the code does compile and only threw an exception for the Read function.

I will change the code to make use of using.

Jon


Hi,

I'm having a problem with deserialising from a file.

I have two buttons on a Windows form (see simplified example code below). The first serialises an
integer value to a file and the second deserialises the same data from the file.

The first function works fine, but the second causes a runtime exception in the "finally" block.
Stepping through in the debugger, stream is set to something sensible in the try section, but
becomes null as soon as it leaves the try section and enters into the finally section, and calling
Close() on the null causes the exception. Curiously, this exception does not occur in the first
function.

1) For each case, does the stream get closed automatically when if falls out of the try{} scope?
If
so, I don't need to have stream.Close() in the finally block. I ask this since when opening a
connection to a database, it is best to explicitly call close, since the GC may not run for a long
time after falling out of scope. I know that closing a stream is not the same as closing a DB
connection, but wondered if similar principles apply?

2) Why does only the second function set stream to null, but not the first function?

I'm using VS 2008 Express, targeting .NET 2.0 on an XP pro PC.

private void btnSaveData_Click(object sender, EventArgs e){
try{
Stream stream = File.Open(@"C:\test.dta", FileMode.Create);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, testInt);
}catch(Exception ex){
// TO DO: add code to recover from exception
}finally{
stream.Close();
}

}

private void btnReadData_Click(object sender, EventArgs e){
try{
Stream stream = File.Open(@"C:\test.dta", FileMode.Open);
BinaryFormatter formatter = new BinaryFormatter();

testInt = (int)formatter.Deserialize(stream);
}catch(Exception ex){
// TO DO: add code to recover from exception
}finally{
stream.Close(); // "stream" is always null here, so get an exception
}

}

Is that your real code? I can't believe that compiles. Since the
Stream is declared inside the try block, it should not be visible in
the catch or finally blocks. I would expect an exception in both
places.

When using Streams (or anything else that implements IDisposable),
it's often cleaner to use a using block:

using (Stream stream = File.Open(@"C:\test.dta", FileMode.Open)) {
BinaryFormatter formatter = new BinaryFormatter();
testInt = (int)formatter.Deserialize(stream);
}

This ensures that the stream is disposed at the end of the using
block.

Chris
 
C

Chris Dunaway

However, both functions in the real code do have the Stream stream = File.Open(...) within the try
and strangely enough the code does compile and only threw an exception for the Read function.

Is it possible that you have a variable called stream defined
somewhere outside the try block and you have simply overlooked it?
Otherwise, I can't see how it would compile.

Chris
 
J

Jon

You are right Chris, I did have stream defined outside the try block. Thanks very much for your help
with this.

The fix for the first function I came up with was:

private void btnSaveData_Click(object sender, EventArgs e){
Stream stream =null; //must assign a value otherwise get a use of unassigned variable compile
error at stream.Close()
try{
Stream stream = File.Open(@"C:\test.dta", FileMode.Create);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, testInt);
}catch(Exception ex){
// TO DO: add code to recover from exception
}finally{
if(stream!=null) stream.Close();
}
}

But as you said, it's best to use using, and this is what I came up with. I'm not completely sure
that I have the try/catch in the right place. I don't think a finally is required.

private void btnSaveData_Click(object sender, EventArgs e){
try{
using(Stream stream = File.Open(@"C:\test.dta", FileMode.Create)){
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, testInt);
}
}catch(Exception ex){
// TO DO: add code to recover from exception
}
}



However, both functions in the real code do have the Stream stream = File.Open(...) within the try
and strangely enough the code does compile and only threw an exception for the Read function.

Is it possible that you have a variable called stream defined
somewhere outside the try block and you have simply overlooked it?
Otherwise, I can't see how it would compile.

Chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top