I'm having a real strange issue while working with streams in mono.
I open a stream like this:
_stream = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
Where _stream of course is a FileStream. I added a dispose method for this class like that:
public override void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if(!_disposed)
{
if(disposing)
{
_stream.Flush(true);
_stream.Dispose();
_items.Clear();
}
_disposed = true;
}
}
Now i have this simple test:
[Test]
public void SimpleTest()
{
SyncFileWriter s = new SyncFileWriter("file");
s.Save("a", "b");
s.Dispose();
SyncFileWriter s2 = new SyncFileWriter("file");
s2.Dispose();
}
But if fails with a IOException: Sharing violation. [edit]It looks like there was an error with monodevelop. Restarted it and now it fails everytime[/edit]
How to avoid this and close the stream properly?
It looks like it was my fault. The SyncFileWriter is derived from a abstract class that checkes whether the file exist, or not. If not, it will initialize this file with some default things and that's why I did the following
File.Create(filename);
As you see, I create a file, but File.Create opens a stream and does not close it after leaving it's scope, whatever.
Now I do this:
Filestream f = File.Create(filename);
...
f.Dispose();
and everything is fine.
I think here lies also the problem for the first nondeterministic behavoir, because it does this only, when a parameter is null, and it is only null, when you create a new file.
Anyway, Thanks for your help!
Not quite sure what you're trying to achieve, but I guess this may help: http://www.blackwasp.co.uk/UsingStatement.aspx
Related
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)
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.
I have a class which uses a StreamWriter to write to a file.
public void CreateLog(string errorLogFilePath, StringBuilder errorLogBuilder, string errorMessage)
{
using (StreamWriter sw = new StreamWriter(errorLogFilePath, true)
{
errorLogBuilder.Apend("An error was discovered.");
//....
sw.Write(errorLogBuilder.ToString());
}
}
[Questions]
1: Is it possible to check that the .Write() method is called?
2: Do i need to wrap a MemoryStream inside the StreamWriter in order to test it, without actually accessing the hard drive. One of StreamWriters constructors accepts a stream but it states the following + will the UTF-8 encoding affect this?
Initializes a new instance of the StreamWriter class for the specified stream by using UTF-8 encoding and the default buffer size.
3: How do you determine if a class is actually accessing the hd and thus needs to be mocked? (sorry if this last question sounds stupid, but im genuinely a little puzzled by this.)
Have the method write to a TextWriter rather than a StreamWriter. Then test the method by passing it a mock TextWriter. In the "real" code, of course, you'll pass in a StreamWriter that was created using new StreamWriter(errorLogFilePath, true).
This yields the following answers to your questions:
Yes
No
You can't generally determine that without decompiling its code.
A little more detail:
Refactor the method into two methods:
public void CreateLog(string errorLogFilePath, StringBuilder errorLogBuilder, string errorMessage)
{
using (StreamWriter sw = new StreamWriter(errorLogFilePath, true)
{
CreateLog(sw, errorLogBuilder, errorMessage);
}
}
public void CreateLog(TextWriter writer, StringBuilder errorLogBuilder, string errorMessage)
{
errorLogBuilder.Apend("An error was discovered.");
//....
writer.Write(errorLogBuilder.ToString());
}
Test the first method to ensure that it calls the second method with an appropriately-constructed StreamWriter. Test the second method to ensure that it calls Write on the passed TextWriter, with appropriate arguments. Now you've abstracted away the dependency on the hard drive. Your tests don't use the hard drive, but you're testing everything.
Generally speaking, you could :
Use a well tested logging library (like NLog, MS Logging Application Block), and spare you developping and maintaining your own.
Refactor your logging logic (or code calling messageboxes, open file dialogs, and so on) into a service, with its interface. This way you can split your testing strategy :
when testing consumers of the loggin service : mock the logging interface to make sure the log method is called. This will ensure that the logging is correctly called by consumers of your logging service
when testing the logging service implementation, just make sure that expected output matches given input : if you want to write "FOO" to bar.log, effectively call
IE :
// arrrange
File.Delete("bar.log")
// act
CreateLog("bar.log", errorLogBuilder, "FOO")
// assert
Assert.IsTrue( File.Exists("bar.log") )
Assert.IsTrue( File.ReadAllLines("bar.log").First() == "FOO")
The point is making sure that the component is called, done by mocking.
Then you can check that the component works as expected.
I know this is a very old question, but I came across this while trying to solve a similar problem.. namely, how to fake the StreamWriter.
The way I went about this was by not having the StreamWriter created inside the method as part of the using statement, but created up front, within the ctor (make your class extend from IDisposable and then destroy the StreamWriter in the Dispose method instead). Then inject a fake over the top of it while under test:
internal class FakeStreamWriter : StreamWriter
{
public List<string> Writes { get; set; } = new List<string>();
public FakeStreamWriter() : base(new MemoryStream()) { }
public override void Write(string value)
{
WriteLine(value);
}
public override void WriteLine(string value)
{
Writes.Add(value);
}
public override void Flush()
{
}
}
My unit test method then looks like this:
public void SmtpStream_Negotiate_EhloResultsCorrectly()
{
var ctx = new APIContext();
var logger = new FakeLogger();
var writer = new FakeStreamWriter();
var reader = new FakeStreamReader { Line = "EHLO test.com" };
var stream = new SmtpStream(logger, ctx, new MemoryStream())
{
_writer = writer,
_reader = reader
};
Exception ex = null;
try
{
stream.Negotiate(ctx);
}
catch (Exception x)
{
ex = x;
}
Assert.IsNull(ex);
Assert.IsTrue(writer.Writes.ElementAt(0) == "250 Hello test.com");
Assert.IsTrue(writer.Writes.ElementAt(1) == "250 STARTTLS");
}
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 :)
I have a class which reads data from one file stream and writes to another. I am concerned about closing the streams after the processing has finished in closeFiles().
How would you handle the possibility that the dispose of one stream may throw an exception stopping the dispose of the other stream from being called.?
Should I be calling close and dispose on the streams or just one?
What happens if I catch any errors from the stream disposes and then continue with moving and deleting of the files as shown in lastOperation()?
In a perfect world I'd like to use a using statement in a c++ style initialisation list but I'm pretty sure that's not possible in c#.
EDIT : thanks for the quick responses guys. So what I should be doing is deriving from IDisposable and then change the constructor and add the two disposing methods like this?:
~FileProcessor()
{
Dispose(true);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
sw.Flush();
}
closeFiles();
disposed = true;
}
}
This is basically what I'm doing:
class FileProcessor
{
private string in_filename;
private string out_filename;
private StreamReader sr;
private StreamWriter sw;
bool filesOpen = false;
public FileProcessor(string filename)
{
in_filename = filename;
out_filename = filename + ".out";
openFiles();
}
~FileProcessor()
{
closeFiles();
}
private void openFiles()
{
sr = new StreamReader(in_filename);
sw = new StreamWriter(out_filename);
filesOpen = true;
}
private void closeFiles()
{
if (filesOpen)
{
sr.Close();
sw.Close();
sr.Dispose();
sw.Dispose();
filesOpen = false;
}
}
/* various functions to read, process and write to the files */
public void lastOperation()
{
closeFiles();
File.Delete( in_filename );
Directory.Move(out_filename, outdir + out_filename);
}
}
Your FileProcessor class should not have a destructor. It is of no use but it is expensive.
It should have a Dispose() (and implement the IDisposable interface) to call closeFiles().
And like #marcelo answered, Stream.Dispose() should not throw. You can rely on this for BCL classes.
But you should check each Reader/Writer for null, in case the first one opened but the second one failed:
if (sr != null) sr.Dispose();
if (sw != null) sw.Dispose();
Your filesOpen can't cover both.
I think it is a good practise to have your class implements IDisposable interface if you are using IDisposable object inside it.
Then, you should make sure that, in your Dispose() implementation, don't throw exceptions. If every object you dispose makes this guarantee, your client will be safe.
Dispose methods should never throw exceptions. There's even a code analysis tool warning for this.
In C#, using does exist. The object provided to the using statement must implement the IDisposable interface. This interface provides the Dispose method, which should release the object's resources.
If your StreamReader and StreamWriter implement IDisposable, you can put them in a using block, and they will be disposed of cleanly when you have finished with them.
using(var sr = new StreamReader(in_filename)) {
// Perform reader actions
}
// Reader will now be disposed.