Disposing of FileStream does not end Asynchronous Read - c#

I open a FileStream to be written to Asynchronously.
m_oFile.BeginRead(arrInputReport, 0, m_nInputReportLength, new AsyncCallback(ReadCompleted), arrInputReport);
I dispose this using the following code:
if (bDisposing)
{
if (m_oFile != null)
{
m_oFile.Dispose();
m_oFile = null;
}
Unfortunately, after calling the dispose method, ReadComplete method still receives results:
protected void ReadCompleted(IAsyncResult iResult)
{
byte[] arrBuff = (byte[])iResult.AsyncState; // retrieve the read buffer
try
{
m_oFile.EndRead(iResult);
It will get a nullReference error at the m_oFile.EndRead line. Checking for null gets rid of the exception but just traps the program in this method. How can I dispose of the ReadComplete method?

If you don't have reliable access to the instance you used, then I would suggest using the AsyncState to store all the things you need. For example:
var state = Tuple.Create(m_oFile, arrInputReport);
m_oFile.BeginRead(...blah... , ReadCompleted, state);
with:
var state = (Tuple<FileInfo, byte[]>)iResult.AsyncState;
FileInfo file = state.Item1;
byte[] arrBuff = state.Item2;
Note a null-check isn't enough, because if a new file has been used, you would be calling it on the wrong FileInfo instance - not a good thing.

Related

Redundant set to null / setting to null in called function

I created a function to make sure an object is disposed of properly. This function includes setting the object to null. I am wondering if the line that sets the object to null is useless (and hence I will remove the line), and then add a line to set the object to null in the calling function. My example is for the FileStream object, but I any other object (I think) can take its place. I know I can trace the execution of the program and see what is happening, however, I would like to know more information on the inner mechanisms (garbage collection?), does this work for any object, etc.
//Called function:
public static void DiscardFile(System.IO.FileStream file)
{
file.Flush();
file.Close();
file.Dispose();
//Does this work?
//When the function returns, is the file object really set to null?
file = null;
}
//Calling function:
public static void WriteStringToFile(string s, string fileName)
{
System.IO.StreamWriter file = new System.IO.StreamWriter(fileName);
file.Write(s);
DiscardFile(file);
//Is this redundant?
//Or is the line in the called function the redundant line?
file = null;
}
Thanks!
I have a loop that writes a thousand strings to files within 30 seconds. (The program will be writing 400K+ strings when it completes its execution.) I see that the loop waits (every so often) at the file.Write(s) line, and that the memory footprint of the app increases. That is for another thread, but wanted to know the behavior of the above code.
Thanks!
Sorry, but your implementation is dangerous
public static void WriteStringToFile(string s, string fileName)
{
System.IO.StreamWriter file = new System.IO.StreamWriter(fileName);
file.Write(s); // <- the danger is here
DiscardFile(file);
//Is this redundant? Yes, it's redundant
//Or is the line in the called function the redundant line?
file = null;
}
Suppose you have an exception thrown on file.Write(s); it means that DiscardFile(file); will never be executed an you have resource leakage (HFILE - opened file handle).
Why not stick to standard using pattern:
public static void WriteStringToFile(string s, string fileName)
{
// Let system release all the resources acquired
using var file = new System.IO.StreamWriter(fileName);
{
file.Write(s);
} // <- here the resources will be released
}
In case of C# 8.0 you can get rid of pesky {...} and let the system release resources on leaving method's scope (see https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#using-declarations):
public static void WriteStringToFile(string s, string fileName)
{
// Let system release all the resources acquired
using var file = new System.IO.StreamWriter(fileName);
file.Write(s);
} // <- here the resources will be released

Finding a memory leak

I have an issue with the following code. I create a memory stream in the GetDB function and the return value is used in a using block. For some unknown reason if I dump my objects I see that the MemoryStream is still around at the end of the Main method. This cause me a massive leak. Any idea how I can clean this buffer ?
I have actually checked that the Dispose method has been called on the MemoryStream but the object seems to stay around, I have used the diagnostic tools of Visual Studio 2017 for this task.
class Program
{
static void Main(string[] args)
{
List<CsvProduct> products;
using (var s = GetDb())
{
products = Utf8Json.JsonSerializer.Deserialize<List<CsvProduct>>(s).ToList();
}
}
public static Stream GetDb()
{
var filepath = Path.Combine("c:/users/tom/Downloads", "productdb.zip");
using (var archive = ZipFile.OpenRead(filepath))
{
var data = archive.Entries.Single(e => e.FullName == "productdb.json");
using (var s = data.Open())
{
var ms = new MemoryStream();
s.CopyTo(ms);
ms.Seek(0, SeekOrigin.Begin);
return (Stream)ms;
}
}
}
}
For some unknown reason if I dump my objects I see that the MemoryStream is still around at the end of the Main method.
That isn't particuarly abnormal; GC happens separately.
This cause me a massive leak.
That isn't a leak, it is just memory usage.
Any idea how I can clean this buffer ?
I would probably just not use a MemoryStream, instead returning something that wraps the live uncompressing stream (from s = data.Open()). The problem here, though, is that you can't just return s - as archive would still be disposed upon leaving the method. So if I needed to solve this, I would create a custom Stream that wraps an inner stream and which disposes a second object when disposed, i.e.
class MyStream : Stream {
private readonly Stream _source;
private readonly IDisposable _parent;
public MyStream(Stream, IDisposable) {...assign...}
// not shown: Implement all Stream methods via `_source` proxy
public override void Dispose()
{
_source.Dispose();
_parent.Dispose();
}
}
then have:
public static Stream GetDb()
{
var filepath = Path.Combine("c:/users/tom/Downloads", "productdb.zip");
var archive = ZipFile.OpenRead(filepath);
var data = archive.Entries.Single(e => e.FullName == "productdb.json");
var s = data.Open();
return new MyStream(s, archive);
}
(could be improved slightly to make sure that archive is disposed if an exception happens before we return with success)

Disposing MemoryStreams and GZipStreams

I want to compress a ProtoBuffer object on serialisation and decompress on deserialisation. Unfortunatly, C# stdlib offers only compression routines that work on streams rather than on byte[], that makes it a bit unesseray more verbose than a function call. My Code so far:
class MyObject{
public string P1 {get; set;}
public string P2 {get; set;}
// ...
public byte[] Serialize(){
var builder = new BinaryFormat.MyObject.Builder();
builder.SetP1(P1);
builder.SetP2(P2);
// ...
// object is now build, let's compress it.
var ms = new MemoryStream();
// Without this using, the serialisatoin/deserialisation Tests fail
using (var gz = new GZipStream(ms, CompressionMode.Compress))
{
builder.Build().WriteTo(gz);
}
return ms.ToArray();
}
public void Deserialize(byte[] data)
{
var ms = new MemoryStream();
// Here, Tests work, even when the "using" is left out, like this:
(new GZipStream(new MemoryStream(data), CompressionMode.Decompress)).CopyTo(ms);
var msg = BinaryFormat.MachineInfo.ParseFrom(ms.ToArray());
P1 = msg.P1;
P2 = msg.P2;
// ...
}
}
When dealing with streams, it seems one has to manually take care of the disposal of the objects. I wonder why that is, I'd expect GZipStream to be fully managed Code. And I wonder If Deserialize works only by accident and if I should dispose the MemoryStreams aswell.
I know I could probably solve this problem by simply using a thrid party compression library, but that's somewhat besides the point of this question.
GZipStream needs to be disposed so it flushes it's final blocks of compression out of its buffer to its underlying stream, it also calls dispose on the stream you passed in unless you use the overload that takes in a bool and you pass in false.
If you where using the overload that did not dispose of the MemoryStream it is not as critical to have the MemoryStream be disposed because it is not writing its internall buffer anywhere. The only thing it does is set some flags and set a Task object null so it can be GCed sooner if the stream lifetime is longer than the dispose point.
protected override void Dispose(bool disposing)
{
try {
if (disposing) {
_isOpen = false;
_writable = false;
_expandable = false;
// Don't set buffer to null - allow TryGetBuffer, GetBuffer & ToArray to work.
#if FEATURE_ASYNC_IO
_lastReadTask = null;
#endif
}
}
finally {
// Call base.Close() to cleanup async IO resources
base.Dispose(disposing);
}
}
Also, although the comment says "Call base.Close() to cleanup async IO resources" the base dispose function from the Stream class does nothing at all.
protected virtual void Dispose(bool disposing)
{
// Note: Never change this to call other virtual methods on Stream
// like Write, since the state on subclasses has already been
// torn down. This is the last code to run on cleanup for a stream.
}
All that being said, when decompressing a GZipStream you can likely get away with not disposing it for the same reason as not disposing the MemoryStream, when decompressing it does not buffer bytes anywhere so there is no need to flush any buffers.

Why does visual studio code analysis warn me that this object can be disposed twice in this code (when it can't)

Code is:
using (MemoryStream memorystream = new MemoryStream(bytes))
{
using (BinaryWriter writer = new BinaryWriter(memorystream))
{
writer.Write((double)100.0);
}
return memorystream.ToArray();
}
Isn't the above code appropriate to properly dispose of both object?
Is the code analysis at all useful? Other than garbage information about variables names and namespaces it seems to complain about a lot of things that are not reality. I am really thinking that maybe it is useful and I am just missing the point.
OKAY to address concerns whether the MemoryStream is disposed of or not (its not) here is an example where the VS code analysis gives me the exact same warning. Clearly nothing is getting disposed of here
public class MyClass : IDisposable
{
public void DoSomethingElse()
{
}
#region IDisposable Members
public void Dispose()
{
throw new NotImplementedException();
}
#endregion
}
public class MyOtherClass : IDisposable
{
public MyOtherClass(MyClass mc)
{
}
public void DoSomething() { }
}
public void Foo()
{
using (MyClass mc = new MyClass())
{
using (MyOtherClass otherclass = new MyOtherClass(mc))
{
otherclass.DoSomething();
}
mc.DoSomethingElse();
}
}
On "If the stream were disposed then how can I call memorystream.ToArray()" part of the question:
MemeoryStream.Dispose does not release internal buffer. The only thing that it does is blocking all Stream methods (like Read) by throwing "Object Disposed" exception. I.e. following code is perfectly valid (usually similar code accessing lower level storage can be written for other other Stream objects that manage some sort of storage):
MemoryStream memoryStream = new MemoryStream();
using (memoryStream)
{
// write something to the stream
}
// Note memoryStream.Write will fail here with an exception,
// only calls to get storage (ToArray and GetBuffer) make sense at this point.
var data = memoryStream.ToArray();
BinaryWriter does not dispose the MemoryStream. YOU NEED TO DISPOSE OF IT. Get the results of .ToArray in a variable, then dispose the MemoryStream, then return the result. Or use a try/finally to dispose of the MemoryStream.
If I were to guess I would say that the logic of the analysis rule is identifying a possiblity that goes someting like this:
"You are passing a disposable object into the constructor of another disposable object (thus semantically implying a transfer of ownership). If ownership is truly being trasnsferred to the second object, it's likely that it will dispose of the object passed to its constructor in its own Dispose method but you're disposing of it as well."
Your second example proves that it is not actually analysing whether or not the second object takes ownership of and disposes the first, but rather this rule is saying this pattern has some semantic ambiguity, as the code responsible for disposal of the first object is no longer clear.
The dispose pattern has all of the inherent pitfalls of alloc/free and new/delete as only one class should own and thus control the lifetime of a disposable instance.
All pure conjecture of course but that's how I'd read it.
MemoryStream wraps a managed buffer that will be garbage collected at some point in the future regardless of whether its disposed of.
The IDisposable implementation is part of the Stream contract. It closes the stream preventing you from using the Read and Write methods but you are still permitted to access the underlying bytes. (Preventing calls to ToArray would probably make it difficult to use with StreamWriters.) A Stream implementation that does use unmanaged resources like a FileStream would release the file handle when it is disposed of.
The code analysis is noting that both you and the StreamWriter are calling Dispose on the same object and warning about it. This is pretty meaningless for a MemoryStream but might be dangerous with some other IDisposable implementations.
You appear to be confusing the IDisposable interface with garbage collection. Calling Dispose does not release managed objects, it just gives your class the opportunity to release unmanaged resources in a deterministic manner.
I think BinaryWriter.Dispose() will call its underlying MemoryStream's .Dispose(), and then your using will re-dispose it.
At least I think that's what will happen. I haven't opened the source for BinaryWriter to verify, but I was always under the impression it closed and disposed its underlying stream.
Edit:
This is the source for the classes. You can see where your memory stream is being disposed:
BinaryStream:
public BinaryWriter(Stream output) : this(output, new UTF8Encoding(false, true))
{
}
public BinaryWriter(Stream output, Encoding encoding)
{
if (output==null)
throw new ArgumentNullException("output");
if (encoding==null)
throw new ArgumentNullException("encoding");
if (!output.CanWrite)
throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotWritable"));
Contract.EndContractBlock();
OutStream = output;
_buffer = new byte[16];
_encoding = encoding;
_encoder = _encoding.GetEncoder();
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
OutStream.Close();
}
MemoryStream:
public class MemoryStream : Stream
{
....
}
Stream
public virtual void Close()
{
Dispose(true);
GC.SuppressFinalize(this);
}
To answer one of your further questions, "why can you still call .ToArray() if MemoryStream has been disposed", well, this test passes just fine:
[TestMethod]
public void TestDispose()
{
var m = new MemoryStream();
m.WriteByte(120);
m.Dispose();
var a = m.ToArray();
Assert.AreEqual(1, a.Length);
}
So the .ToArray() method is still accessible after dispose.
The bytes are still available. MemoryStream dispose just sets some flags internally that prevent you from further modifying the stream:
protected override void Dispose(bool disposing)
{
try {
if (disposing) {
_isOpen = false;
_writable = false;
_expandable = false;
// Don't set buffer to null - allow GetBuffer & ToArray to work.
}
}
finally {
// Call base.Close() to cleanup async IO resources
base.Dispose(disposing);
}
}
In fact, note that the source has the comment in it:
// Don't set buffer to null - allow GetBuffer & ToArray to work.
so that really answers that question :)

C# "using" blocks

I've got something like the code below...someone here mentioned that the WebClient, Stream, and StreamReader objects could all benefit from using blocks. Two easy questions:
1: How would this little snippet look with using blocks? I've no problem with doing my own research so resource links are fine but it'd be quicker and easier to just see an example and I'll understand it from that.
2: I'd like to get in the habit of good coding standards, would help if I knew a little about the reasons why using blocks are better...is it just so you don't have to worry about closing or are there more reasons? Thanks!
WebClient client = new WebClient();
Stream stream = client.OpenRead(originGetterURL);
StreamReader reader = new StreamReader(stream);
JObject jObject = Newtonsoft.Json.Linq.JObject.Parse(reader.ReadLine());
string encryptionKey = (string)jObject["key"];
string originURL = (string)jObject["origin_url"];
stream.Close()
reader.Close()
using (var client = new WebClient())
using (var stream = client.OpenRead(originGetterURL))
using (var reader = new StreamReader(stream))
{
var jObject = Newtonsoft.Json.Linq.JObject.Parse(reader.ReadLine());
var encryptionKey = (string)jObject["key"];
var originURL = (string)jObject["origin_url"];
}
or simply:
using (var client = new WebClient())
{
var json = client.DownloadString(originGetterURL);
var jObject = Newtonsoft.Json.Linq.JObject.Parse(json);
var encryptionKey = (string)jObject["key"];
var originURL = (string)jObject["origin_url"];
}
using (WebClient client = new WebClient())
{
// do work
}
Provides a convenient syntax that ensures the correct use of IDisposable objects.
From MSDN: using Statement (C# Reference)
As a rule, when you use an IDisposable object, you should declare and instantiate it in a using statement. The using statement calls the Dispose method on the object in the correct way, and it also causes the object itself to go out of scope as soon as Dispose is called. Within the using block, the object is read-only and cannot be modified or reassigned.
The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler.
using(WebClient client = new WebClient()) {
}
is the same as
WebClient client;
try {
client = new WebClient();
} finally {
if(client != null) {
client.Dispose();
}
}
A lot easier to use using
Its simple :
Using *using* is not "good practice" as such, more a short way (syntactic sugar) of disposing objects that you should be disposing. Things like Files, Connections to a Database and in your case a network.
You would do something like:
using(WebClient we = new WebClient))
{
//do something with 'we' here
}
This is basically just a shortcut for using the variable we normally and then calling we.Dispose() which does a clean up.
Syntax :
using (<Any class that Implements IDisposable>)
{
//use the class
}
Other SO questions you should see:
What is the relationship between the using keyword and the IDisposable interface?
using various types in a using statement (C#)
using {} blocks simply call Dispose() at the closing brace--or rather, tell the Garbage Collector that it can dispose of the object. You'd use it like:
using (WebClient client = new WebClient())
{
Stream stream = client.OpenRead(originGetterURL); StreamReader reader = new StreamReader(stream);
JObject jObject = Newtonsoft.Json.Linq.JObject.Parse(reader.ReadLine()); string encryptionKey = (string)jObject["key"]; string originURL = (string)jObject["origin_url"];
stream.Close() reader.Close()
} // 'client' instance gets disposed here
Something like this:
using(WebClient client = new WebClient())
using(Stream stream = client.OpenRead(originGetterURL))
StreamReader reader = new StreamReader(stream) {
JObject jObject = Newtonsoft.Json.Linq.JObject.Parse(reader.ReadLine());
string encryptionKey = (string)jObject["key"];
string originURL = (string)jObject["origin_url"];
}
As for why using blocks are good, and better than manually calling Dispose... image if any of the code in that using block threw an exception before you hit the lines where you close everything? You'd essentially leak whatever unmanaged resource the IDisposable object is managing under the hood. using ensures that Dispose is called correctly, even in the face of an exception (by essentially injecting the appropriate try/finally block).
When possible (i.e., you don't have to preserve the lifetime of some IDisposable across scopes), you should leverage using blocks if for no other reason than they reduce the amount of boilerplate code you have to write in order to ensure your own code is safe and correct.
#Darin's answer shows the code. The reason they are good is that using blocks cause the compiler to spit out code that will automatically call "Dispose" on the object (to have it immediately release any resources it may be using) before exiting the block - even if an exception gets thrown within with the block
using is equivalent to try.. finally so the disposer will run even if an exception is thrown within the block.
There are 2 reasons for using-blocks:
They look good
The code inside the block often could throw exceptions. So you wold need try-finally
In the end a using-block e.g.
using (Somthing somthing=...)
{
DoActions(somthing);
}
is identical to the followin contstruct:
{Somthing somthing=...
try
{
DoActions(somthing);
}
finally
{
somthing.Dispose();
}
}//the outer bracket limits the variable

Categories