I'm working on a database and I need to write the database to file when the database class is destroyed along with every else when the form is closed
This is how I'm currently calling it:
class database: IDisposable
{
List<databaseEntry> dDatabase;
public database()
{
dDatabase = new List<databaseEntry>;
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
StreamWriter sw = new StreamWriter(path);
string toWrite;
foreach (databaseEntry dE in dDatabase)
{
toWrite = dE.rfid.ToString() + " " + dE.currentArea.ToString() + " " + dE.itemName;
sw.WriteLine(toWrite);
}
sw.Close();
disposed = true;
}
}//destructor for database (saves database to file)
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
The Dispose method isn't called when I close the windows form that this class is open in.
This is for an assignment and I'm not allowed to use SQL for this.
You do not have control over when the Dispose method is called by the garbage collector. If you want to dispose resources when the form is closed, you should manually call the Dispose method when the form is closed.
This is achieved by listening to the FormClosed event of the form.
So you would do something similar to this:
Create this method:
private void Form1_FormClosed(Object sender, FormClosedEventArgs e)
{
if(this.database != null)
this.database.Dispose();
}
Put this line in your form's constructor:
this.FormClosed += Form1_FormClosed;
Since you're implementing IDisposable, another solution would be to wrap your database object instantiation in a using statement - this would automatically call Dispose once the code in the using statement completes.
Syntax for your use case is as follows:
using(database db = new database())
{
//use your db object
} //db is disposed here
Edit:
Matthew Watson’s comment made me realize my answer is over simplified and could be confusing (thanks for the comment Matthew). Here’s (most of) the real story:
All objects have a constructor and a destructor. If these are not specified the default constructor and destructor are used.
Constructor:
ClassName()
Destructor:
~ClassName()
The Constructor is called when you use the new keyword. The Destructor can be called once there is no longer a reference to that specific instance of an object. Notice I said can be called, not is called. Meaning at this point the object is eligible for garbage collection and could be freed when the garage collector runs. I will not go into detail here but just know that the garage collector does not always collect all the unreachable objects for performance reasons. This is one of the key reasons you would want to the IDisposable interface. You can immediately clean up resources when you know they are no longer being used vs. waiting for the GC to clean up the resources. When working with streams or database connections it is a good idea to implement the IDisposable interface.
With that said here is the updated answer (replacing the previous "default Dispose()" references with the destructor reference).
Since this is an assignment I am not going to give you the answer per se, but I'll get you close. The destructor (~database) is normally called by the garage collector when an instance of a database object is no longer reachable. By implementing the IDisposable interface you have provided an alternative to allowing the garage collector to dispose of the object. You are telling the garage collector "I know when and how these resources need to be freed" vs. free these resources when there are no longer references to the objects. But that only applies if you call your Dispose method; more specifically the line:
Dispose(true);
GC.SuppressFinalize(this);
This means "Garage collector, do not call the destructor (~database()) method, I have already handled it".
What you should do in this method is close any streams (StreamWriter) you have open.
Usage: The IDisposable interface has a nice construct in C# the using statement. This is in effect a try catch block where the Dispose method is called in the finally block. StreamWriter also implements IDisposable so you should think about implementing the using statement in your database class. Example:
using(StreamWriter writer = new StreamWriter()){
//do stuff with writer here
}
This is the pattern you should use for your database class in your form. I will let you figure out how to code that up.
Related
I have the following logger-like class pattern:
public class DisposableClassWithStream : IDisposable
{
public DisposableClassWithStream()
{
stream = new FileStream("/tmp/file", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
writer = new StreamWriter(stream);
}
public void WriteLine(string s)
{
writer.WriteLine(s);
}
~DisposableClassWithStream()
{
Dispose();
}
private readonly object disposableLock = new object();
private bool isDisposed;
public void Dispose()
{
lock (disposableLock)
{
if (!isDisposed)
{
writer.Close();
stream.Close();
GC.SuppressFinalize(this);
isDisposed = true;
}
}
}
private FileStream stream;
private TextWriter writer;
}
and a very simple code using this class:
public static void Main(string[] args)
{
var t = new DisposableClassWithStream();
t.WriteLine("Test");
}
The code throws (nondeterministically), both on .net and mono, ObjectDisposedException caused by method Close of object writer as it tries to flush buffer to stream which is already disposed.
I understand that the reason is that GC finalizes stream before writer. How can I change the class pattern to be sure that stream is not disposed before the writer?
I tired to use GC.SuppressFinalize(writer) in the constructor, but I'm not sure if it is not too hacky.
Edit:
I would like to address the question of having finalizer in the first place. As mentioned at the beginning of the question, the class is used as a logger and I want to assure that all lines from writer are flushed to the hard disk before closing the process.
Do not create finalizer, unless your IDisposable implementation really works with unmanaged resources. FileStream and StreamWriter are managed resources.
Moreover, since SafeHandle was introduced, it is hard to imagine use-case, when any unmanaged resource couldn't be wrapped into managed SafeHandle. Do not follow blindly IDisposable implemetation from MSDN - it's OK, but it is intended for the case, when your type operates both managed and unmanaged resources.
Remove finalizer at all, and throw away GC.SuppressFinalize(this); from Dispose:
public void Dispose()
{
lock (disposableLock)
{
if (!isDisposed)
{
writer.Close();
stream.Close();
isDisposed = true;
}
}
}
Update.
Finalizers are intended for unmanaged resource cleanup.
You may consider finalizer as a place to close file handle, network socket, etc. This isn't a place for any application logic. In general, managed object during finalization resides in unusable state - there's no guarantee, that any of its IDisposables (like stream or writer in your sample) are not finalized already.
If you want to be sure, that particular log message is flushed into file, than write it and call writer.Flush(). Otherwise, if immediate flushing is undesirable for you, make sure, that you're calling dispose for the logger on application shutdown. Also note, that you can't protect from process termination, so don't be too paranoid with your logger.
Managed objects should not be cleaned up in the finalizer. The finalizer should only used for cleaning up unmanaged resources.
Rewrite your code as follows to dispose of managed resources when you are done with the streams.
public static void Main(string[] args)
{
using (var t = new DisposableClassWithStream())
{
t.WriteLine("Test");
}
}
And be sure to check out the Dispose Pattern article on MSDN
When a finalizer runs, most managed objects to which it holds references will meet one of the following criteria:
-1- Not care about cleanup, in which case the finalizer should do nothing with them.
-2- Be unable to perform cleanup in a thread-safe manner when invoked in the context of finalizer cleanup, in which case the finalizer should do nothing with them.
-3- Have already cleaned themselves up using their own finalizer, in which case the finalizer should do nothing with them.
-4- Have a Finalize method which hasn't run yet, but is scheduled to run at first opportunity, in which case the finalizer for the class holding the reference should do nothing with them.
Different objects will meet different criteria, and it may be difficult to know which of those criteria a particular object might meet, but for the vast majority of objects will meet any of the criteria, the required handling is the same: don't do anything with them in the finalizer.
There are a few rare scenarios involving things like weak events where finalizers may be able to do something useful with managed objects, but in nearly all such cases, the only classes which should have finalizers are those whose sole purpose is to managed the finalization cleanup of other intimately-related objects. If one doesn't understand all the wrinkles of finalization, including the differences between short and long weak references and how they interact with the finalizer, any finalizer one tries to write will likely do more harm than good.
I want to know if IDisposable objects will dispose on session ending.
I know, I can dispose on Session ending event myself. But I want to write an IDisposable class.
For example, I have
public class MyObject : IDisposable
{
// some properties
public void Dispose()
{
// disposing
}
}
and I need to dispose this object on session ending time :
protected void Session_End(object sender, EventArgs e)
{
if (Session["key"] != null)
((MyObject)Session["key"]).Dispose();
}
So, I want to know on session ending time that operation will automatically or I need write as above.
Session_End does not automatically dispose of IDisposable objects, so your Session_End solution is correct.
However:
Session_End is only called when you use "inproc" sessions (but for the other types you would need a serializable object)
It's only called after the session timeout has expired, so you kept this resource for an extra 20 minutes (or whatever your timeout is)
So try and find a solution that doesn't require you to store IDisposable objects in Session.
An instance of a class which implements the IDisposable interface will only be "disposed" whenever you call the Dispose method, whether directly or indirectly via the using construct. It's not something which happens automatically whenever an object falls out of scope.
For example, this would be bad practice;
public void SomeMethodCalledDuringSession()
{
var resourceHog = new ResourceHog(); // where ResourceHog : IDisposable
// Perform operations
}
The object is never disposed properly here, regardless of your ASP.NET session ending. However, you can call Dispose directly when you're finished, or a better idea is to do this;
public void SomeMethodCalledDuringSession()
{
using(var resourceHog = new ResourceHog()) // where ResourceHog : IDisposable
{
// Perform operations
}
}
This translates into a try ... finally pattern, with the call to Dispose in the finally clause, ensuring that it gets called (apart from a few rare situations).
Edit: I would also read this; http://nitoprograms.blogspot.co.uk/2009/08/how-to-implement-idisposable-and.html
Does the following psuedo code accomplish my goal of cleaning up after myself when my DLL is being hosted by code I don't control?
More specifically, how do I clean up my objects created in my static constructor?
Do I need to suppress Finalize in the Disposable?
Am I guaranteed that the compiler or something will call IDisposable even if the Host doesn't?
Psuedo code:
public class MyDLL : SomeHostICantControl, IDisposable
{
public SpinLock MyDictionarySpinlock = new Spinlock; // approximate syntax
public static Dictionary<string, string> MyDictionary = null;
public static Timer MyCleanUpTimer = null;
public static MyDLL()
{
// Set up Cache Here ... how do I dispose of it?
MyDictionary = new Dictionary<string, string>();
// remove old data from the dictionary, use spinlock to sync writes
// or use concurrent dictionary in .NET 4
MyCleanUpTimer = new Timer(); // run every hour
}
// many instances will be created and disposed of. I have no control when or how often
public void MyDll()
{
this.MyHostEvent += New Event Handler....
}
//.. some event handler code here
public void Dispose()
{
this.MyHostEvent -= Event Handler.;
// Do I need to suppressFinalize here?
}
//~MyDll()
//{
// Is this the right place to clean up after my constuctor?
//}
}
Answering your questions in order:
Static fields exist for the lifetime of the application, as such they are "cleaned up" as a result of the application exiting (memory is reclaimed, files are closed etc.). You don't appear to be doing anything that might require explicit action to be taken to clean-up (e.g. flushing buffered data in a StreamWriter to file), but perhaps there are details missing in your code snippet.
You need to suppress finalize in your Dispose() method if your class has a finalizer (yours appears not to as it's commented out), or if someone can derive from your class and may introduce unmanaged resources that may need cleaning up. The latter applies here as your class is not marked sealed, so you should suppress finalize in Dispose().
The runtime will not call Dispose(), however it will call the finalizer if one is present. Note however that as you class instances don't appear to be using any unmanaged resources, a finalizer should not be required.
I'm currently do a review of a C# app in which I see that :
public static bool ServiceExists(string servicename)
{
ServiceController[] services = ServiceController.GetServices();
foreach (ServiceController s in services)
{
if (s.ServiceName == servicename)
{
return true;
}
}
return false;
}
In this answer, Henk said that the non-use of Dispose() (or using) will not generate memory leaks, true or false?
Can I keep the previous code has it is or should I write someting like :
public static bool ServiceExists(string servicename)
{
ServiceController[] services = ServiceController.GetServices();
bool exists = false;
foreach (ServiceController s in services)
{
using(s)
{
if (s.ServiceName == servicename)
{
exists = true;
}
}
}
return exists;
}
What are the risks to no using Dispose() (or using) in this case?
A correctly written object shouldn't cause a memory leak if it's Dispose method isn't called. These days a .Net object which controls unmanaged resources should be doing so via a SafeHandle instance. These will ensure the native memory is freed even if Dispose is not called.
However it's very possible for objects which aren't written correctly to produce memory leaks if Dispose isn't called. I've seen many examples of such objects.
In general though if you are using an IDisposable instance which you own you should always call Dispose. Even if the object is correctly written it's to your benefit that unmanaged resources get cleaned up earlier instead of later.
EDIT
As James pointed out in the comments there is one case where not calling Dispose could cause a memory leak. Some objects use the Dispose callback to unhook from long lived events which if they stayed attached to would cause the object to reside in memory and constitute a leak. Yet another reason to always call Dispose
It all depends on what ServiceController.GetServices() is doing. If it is creating new instances of ServiceControllers when it is called, then it could cause a memory leak depending on what it needs to do (the ServiceController) in its Dispose method.
That said, adding 'using' in this case wouldn't fix it anyway as if you DID need to call dispose (implicitly via 'using' in this case) on each instance, it WOULDN'T as it returns whenever it finds a ServiceController with a matching name.
Therefore, if your first iteration found a matching ServiceController, all the other ServiceControllers wouldn't get disposed of anyway.
I encapsulate my linq to sql calls in a repository class which is instantiated in the constructor of my overloaded controller. The constructor of my repository class creates the data context so that for the life of the page load, only one data context is used.
In my destructor of the repository class I explicitly call the dispose of the DataContext though I do not believe this is necessary.
Using performance monitor, if I watch my User Connections count and repeatedly load a page, the number increases once per page load. Connections do not get closed or reused (for about 20 minutes).
I tried putting Pooling=false in my config to see if this had any effect but it did not. In any case with pooling I wouldn't expect a new connection for every load, I would expect it to reuse connections.
I've tried putting a break point in the destructor to make sure the dispose is being hit and sure enough it is. So what's happening?
Some code to illustrate what I said above:
The controller:
public class MyController : Controller
{
protected MyRepository rep;
public MyController ()
{
rep = new MyRepository();
}
}
The repository:
public class MyRepository
{
protected MyDataContext dc;
public MyRepository()
{
dc = getDC();
}
~MyRepository()
{
if (dc != null)
{
//if (dc.Connection.State != System.Data.ConnectionState.Closed)
//{
// dc.Connection.Close();
//}
dc.Dispose();
}
}
// etc
}
Note: I add a number of hints and context information to the DC for auditing purposes. This is essentially why I want one connection per page load
Update:
After having implemented IDisposable on my repository and on my controller class I couldn't find a way to specifically call the Dispose method on my controller as the controller is created and destroyed behind the scenes by the MvcHandler. However I did find that my connections were being closed anyway. I wasn't comfortable knowing that this was working but not knowing why so I did some digging and found an MSDN quote that made me happy:
When execution is complete, the MvcHandler will check if the controller implements the IDisposable interface, and if so, will invoke Dispose on the controller to clean up unmanaged resources.
Final Update:
After a month or so with working this I've now removed all this code and gone down the MS advised route of wrapping a "using" statement around the code in my public repository methods and passing this DC into the private methods. This seems a little wasteful and repetitive as well as resulting in a few more connections being opened and closed. But I was getting linq to sql caching that I could only resolve by resetting the DC.
The correct pattern (short but sufficient version) here is:
public class MyRepository : IDisposable
{
... // everything except the dtor
public void Dispose()
{
if (dc != null)
{
dc.Dispose();
}
}
}
public class MyController : Controller, IDisposable
{
protected MyRepository rep;
public MyController ()
{
rep = new MyRepository();
}
public void Dispose()
{
if (rep!= null)
{
rep.Dispose();
}
}
}
And now you can (should) use MyController with the using clause:
using (var ctl = new MyController ())
{
// use ctl
}
Edit:
Just noticed it cascades to MyController, code added. This shows how indirect ownership of an unmanaged resource spreads out.
Edit 2:
This also correct (as would be a try/finally):
var ctl = GetController ();
using (ctl)
{
// use ctl
}
If you can't keep it local to 1 method, just do your best to call ctl.Dispose() in a Closing event or such.
Destructors are only called by the GC. Your MyRepository should implement the Dispose pattern, and dispose of the dc there.
See this question for more detail. In C# what is the difference between a destructor and a Finalize method in a class?
MyRepository should implement IDisposable, any disposable objects should be disposed of there if you are holding them open for the life time of the object.
Most of the time when you are using a Disposable object you should wrap it in a using block
i.e.
using(var dc = getDC())
{
//do stuff with the dc
}//the dc will be Disposed here
Edit: Link to Language guide for c# destructors
http://msdn.microsoft.com/en-us/library/66x5fx1b(v=VS.100).aspx
I agree with the fact that disposable pieces were incorrect and the suggestions above by Henk Holterman and Darryl Braaten are very good ones i don't think it answers your underlying question.
The answer to your question is that calling Dispose on MyRepository (assuming its an DataContext) does not close the connection. It just returns the connection to the pool for next use.
This SO Post, explains when you should worry about closing connections...