Consider the following piece of code:
public static Stream OpenWavStream(string path)
{
var stream = new FileStream(path, FileMode.Open);
try
{
stream.Seek(44, SeekOrigin.Current);
}
catch (Exception)
{
stream.Dispose();
throw;
}
return stream;
}
I'm opening a wav stream whose data always starts at offset 44. If seeking to that offset fails, the stream is disposed, otherwise it is returned. Considering that catch (Exception) is considered bad practice, is it appropriate in this case?
Should one rather research the concrete exceptions (even though the stream should be disposed if any kind of exception happens within the Stream.Seek call) or move it into a finally block?
Only if the Stream fails to load. Something I use:
string fileName = "C:\\PCM.wav";
if (!System.IO.File.Exists(fileName))
{
LogStatus("Wave file not found.");
return;
}
else
{
WaveFileByteArray = File.ReadAllBytes(fileName);
LogStatus("Wave file Loaded!" + Environment.NewLine);
}
This works fine.
then to play/Use:
System.Media.SoundPlayer soundPlayer;
soundPlayer.Stream.Seek(0, SeekOrigin.Begin);
soundPlayer.Stream.Write(WaveFileByteArray, 0, WaveFileByteArray.Length);
soundPlayer.Play();
Relying on an Exception to catch possible errors, like is presented, is not best practice, unless the error is unexpected. Dealing with possible Errors before they occur is best practice.
catch (Exception) is bad practice if you are using it to swallow exceptions and not handling them. You are immediately re-throwing the exception, and doing it properly (you're not doing throw ex; for example). You will need to dispose the stream for any exception, so you should not catch specific exceptions here.
Your code is perfectly fine. However, I am skeptical about the usefulness of the method. Without seeing the rest of the application, it might make sense for the callee to create the stream within a using block, even with a helper method.
//In your callee code
using (var stream = new FileStream(path, FileMode.Open))
{
ConfigureStream(steam);
//Other stuff..
}
public static void ConfigureStream(Stream stream)
{
stream.Seek(44, SeekOrigin.Current);
}
Or, you could check the length of the stream first, to avoid the exception entirely.
Why not use a using block in calling method and leave the closing of steam to the system. using will close the stream even if there is an exception.
public static Stream OpenWavStream(string path)
{
var stream = new FileStream(path, FileMode.Open);
stream.Seek(44, SeekOrigin.Current);
return stream;
}
public static void UseWaveStream()
{
try
{
using(Stream thisStream = OpenWavStream("C:\\myfile.txt"))
{
// do whatever
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
Related
I am serializing a class with a binaryformatter and compressing the data with deflatestream. The save function is as follows and is called from a backgroundworker:
public static void save(System system, String filePath)
{
//Make filestream
FileStream fs = new FileStream(filePath, FileMode.Create);
try
{
//Serialize offerte
BinaryFormatter bf = new BinaryFormatter();
DeflateStream cs = new DeflateStream(fs, CompressionMode.Compress);
bf.Serialize(cs, system);
//Push through
fs.Flush();
cs.Flush();
cs.Close();
}
catch (Exception e)
{
var mess = e.Message;
}
finally
{
//Close
fs.Close();
}
}
The class has a number of 'users'. With 100 users it takes 10 seconds and the file is 2MB. With 1000 users it gives an out-of-memory exception (the estimated size is 16MB). Can anyone see a problem here, or give suggestions how to solve this?
(I was first thinking the time on a background thread was causing this, it takes to long. But I have other background threads that can run longer.)
You aren't disposing of your streams, which may be part of the problem, suggest:
public static void save(System system, String filePath)
{
//Make filestream
using(FileStream fs = new FileStream(filePath, FileMode.Create))
{
//Serialize offerte
BinaryFormatter bf = new BinaryFormatter();
using (DeflateStream cs = new DeflateStream(fs, CompressionMode.Compress)) {
bf.Serialize(cs, system);
//Push through
fs.Flush();
cs.Flush();
cs.Close();
}
}
}
This also removes your exception swallowing, which would probably be a good thing.
You use several objects of classes that implement System.IDisposable
If a designer implemented IDisposable he informs you that he might use scarce resources. You might get out of resources before the garbage collector collects the garbage.
In other words: whenever you use a class that implements System.IDisposable you should call Dispose() as soon as you don't need the class anymore. This is especially needed if you need the resources of the class for something else.
You use two Stream classes: FileStream and DeflateStream. They both implement IDisposable. If you don't call Dispose(), the garbage collector eventually will, but in the mean time the resources that these Streams use are not available for anyone else.
The most easy method to make sure that a Disposable object is disposed is by using the using statement:
using (var myStream = new FileStream(...))
{
... // use myStream
}
When the closing bracket is reached, myStream.Dispose() is called, effectively releasing all scarce resources it uses.
This works on every method that is used to leave the {...} block, including break, return, and even Exceptions.
Therefore using is a very safe method: Dispose() will always be called.
By the way: Dispose() will also take care that the Streams are Flushed and Closed, so at the end of the using statement you don't have to Flush() and Close().
What is the difference between code like this:
string path = #"c:\users\public\test.txt";
System.IO.StreamReader file = new System.IO.StreamReader(path);
char[] buffer = new char[10];
try
{
file.ReadBlock(buffer, index, buffer.Length);
}
catch (System.IO.IOException e)
{
Console.WriteLine("Error reading from {0}. Message = {1}", path, e.Message);
}
finally
{
if (file != null)
{
file.Close();
}
}
and this:
string path = #"c:\users\public\test.txt";
System.IO.StreamReader file = new System.IO.StreamReader(path);
char[] buffer = new char[10];
try
{
file.ReadBlock(buffer, index, buffer.Length);
}
catch (System.IO.IOException e)
{
Console.WriteLine("Error reading from {0}. Message = {1}", path, e.Message);
}
if (file != null)
{
file.Close();
}
Is really finally block necessary in this construction. Why Microsoft provided such construction? It seems to be redundant. Isn't it?
Imagine if some other exception occurred that you haven't handled, e.g. an ArgumentOutOfRangeException, or if you want to rethrow the exception or throw a wrapped exception from your catch block:
The first block would ensure that the file is closed regardless of whether or not an exception occurred.
The second block would only close the file if either no exception occurred or an IOException occurred. It does not handle any other cases.
The first block will close the file even if there is an uncaught exception.
The second block will close the file only if there are no exceptions, or any thrown exceptions are caught.
The first will also ensure that the file is closed if the try has a break, goto, return, continue, or any other jump construct that would cause the execution to move outside of the try block. The second doesn't, and as such it could result in the resource not being closed.
In your example, if your code throws an exception other than System.IO.IOException, your cleanup code is not guaranteed to run. With the finally block, the code within it will run no matter what type of exception is thrown.
In that case it's redundant.
It's usefull if you for example will rethrow an exception and still want some code to run after the block:
try {
// do something dangerous
} catch(...) {
// log the error or something
throw; // let the exception bubble up to the caller
} finally {
// this always runs
}
// this only runs if there was no exception
Another example is if the catch may throw an exception for a different reason:
try {
// do something dangerous
} catch(...) {
// handle the error
// log the error, which may cause a different exception
} finally {
// this runs even if the catch crashed
}
// this only runs if there was no exception, or the code in the catch worked
Simply, as code might crash for plenty of reasons you might not even know about, it's useful to put the cleanup in a finally block just to be sure that it runs whatever happens.
Imagine there was an exception inside catch{}, code inside finally would still run but if (file != null){} block will not.
Using the following code, we got the error 'Object is currently in use elsewhere'
private void CaptureDone(System.Drawing.Bitmap e)
{
try
{
this.pictureBox.Image = e;
if (isSending)
ThreadPool.QueueUserWorkItem(new WaitCallback(SendVideoBuffer), pictureBox.Image);
}
catch (Exception) { }
}
void SendVideoBuffer(object bufferIn)
{
TcpClient tcp = new TcpClient(ConfigurationSettings.AppSettings[0].ToString(), 6000);
NetworkStream ns = tcp.GetStream();
if (ns != null)
{
System.Drawing.Image buffer = (System.Drawing.Image)bufferIn;
buffer.Save(ns, System.Drawing.Imaging.ImageFormat.Jpeg);// error comes here
ns.Close();
tcp.Close();
}
}
Please give suggestions.
GDI+ images are not thread safe, you need to aquire lock on the object.
void SendVideoBuffer(object bufferIn)
{
var tcp = new TcpClient(ConfigurationSettings.AppSettings[0].ToString(), 6000);
var ns = tcp.GetStream();
if (ns != null)
{
var buffer = (System.Drawing.Image)bufferIn;
lock(buffer)
buffer.Save(ns, System.Drawing.Imaging.ImageFormat.Jpeg);
ns.Close();
tcp.Close();
}
}
I encountered such exception before and have more foundings on it.
Most of the reasons for this exception is caused by multi-thread, where we try to operate a same one global image.
Here is a good explain why this exception happens: "With WinForms, this generally means there is a recursive Graphics.GetHdc occurring. GetHdc must match a ReleaseHdc before any other GetHdc. Recursive means you have something like GetHdc->GetHdc->ReleaseHdc->ReleaseHdc, instead of GetHdc->ReleaseHdc->GetHdc->ReleaseHdc. Another possibility is that there is a missing call to ReleaseHdc. (i.e. GetHdc->GetHdc->ReleaseHdc)".
Deep into the image.Save method more, it will call GetHdc->ReleaseHdc pair method. Also, I guess if we try to get image.width or image.Clone methods, it also will call GetHdc method.
So, be careful when try to use a global image in threads. Most of the operations are not thread safe.
I have an issue from time to time, I have a few StreamReaders and StreamWriters in my program that read info and write it. They go right about 99% of the time, but once in a while I end up with a StreamWriter that won't close, on a piece of code I've run multiple times.
This tends to happen if I spam a function, but I am trying to find a safe way to guarantee a steam disposed. Anyone know how?
try a using statement MSDN
using (StreamWriter stream = new StreamWriter(Initialization)){
//your code
}
this can be useful:
Closing Stream Read and Stream Writer when the form exits
Also you could use a Try Block
try
{
//Declare your streamwriter
StreamWriter sw = new StreamWriter(Initialization);
}
catch
{
//Handle the errors
}
finally
{
sw.Dispose();
}
If the stream's scope is local, always use the following construct:
using (var stream = new Stream())
{
...do stream work here...
}
If on the other hand you are using the stream as a class field then implement the IDisposable pattern and dispose your stream objects when disposing your class: IDisposable
Wrapping the StreamWriter in a using statement is how I usually ensure it is disposed of.
using (var writer = new StreamWriter(#"C:\AFile.txt"))
{
//do some stuff with writer
}
An alternative would be to use a finally block.
If I create a stream inside of the try block and an exception is raised does the stream automatically get disposed of? For example:
try
{
Stream stream = response.GetResponseStream();
//Error Occurs
stream.Close();
}
catch
{
//Handle Error
}
If this is not the way to do it can you please suggest an approach?
No, you need to use finally
Stream stream;
try
{
stream = response.GetResponseStream();
//Error Occurs
}
catch
{
//Handle Error
}
finally
{
if(stream != null)
stream.Close();
}
Or, wrap your Stream declaration/definition in a using statement, which calls Close() automatically:
try
{
using(Stream stream = response.GetResponseStream())
{
//Error happens
}
//stream.Dispose(), which calls stream.Close(), is called by compiler here
}
catch
{
//Handle Error
}
Note that my two examples are not exactly equivalent - in the first, the exception is handled before steam.Close() is called, in the second the exception is handled after.
The stream will not automatically close in this case.
If you wanted to ensure it closes in this context you'll want to use finally to ensure closure.
Alternatively I'd wrap the whole stream in a using.
using(Steam stream = response.GetResponseStream())
{
// Do your work here
}
No, use a using block. It calls Dispose automatically when block finishes, even if an error occurs.
eg.
using (Stream stream = response.GetResponseStream())
{
// do something with stream
}
It's the same as:
Stream stream = null;
try
{
stream = response.GetResponseStream();
// do something with stream
}
finally
{
if (stream != null)
stream.Dispose();
}
There are many examples on the net. A quick Google revealed the following already on stackoverflow: 'using' statement vs 'try finally'
using (Stream stream = response.GetResponseStream())
{
}
Dispose() is called on scope exit. This is the correct idiom for ensuring cleanup of IDisposable objects.
using(resource) statement will take care of calling dispose.
The answer is no. It's best to close all resources in a finally block if you have some exception handling logic around your code.
No, to always ensure disposal, regardless of exceptions, you use:
try
{
Stream stream = response.GetResponseStream();
//Error Occurs
}
catch
{
//Handle Error
}
finally
{
if(stream!=null)
stream.Close();
}
or simply:
using (Stream stream = response.GetResponseStream())
{
}
Stream implements IDisposable interface.
You can use using() statements where the class implements IDisposable.
This will automatically take care of closing and disposing the object without writing finally.
try
{
using (var stream = response.GetResponseStream())
{
//Error happens
}
}
catch
{
//Handle Error
}