This question already has answers here:
Why does my destructor never run?
(6 answers)
Closed 9 years ago.
I have a class Class that creates a Thread in it's constructor. This thread runs a while(true) loop that is reading non-critical data from a NetStream. The thread will be aborted by the destructor:
~Class()
{
_thread.Abort();
_thread = null;
}
When the program wants to end the use of Class's instance - ClassInstance, it calls:
ClassInstance = null;
GC.Collect;
I thought that means that ~Class() will be caller automatically at that point - but it's not.
This thread keeps running even after Application.Exit() and returning from Main().
The crucial bit of your code is not included; how the thread is started and what method it is running. If I had to make a guess I would say it is likely you started the thread by passing an instance method of Class. So basically your class instance is still rooted by the running of the thread. You attempt to stop the thread in the finalizer, but the finalizer will never run because the instance is still rooted leading to a catch-22 situation.
Also, you mentioned that the thread is running non-critical code and that was your justification for using Thread.Abort. That really is not a good enough reason. It is very hard to control where that ThreadAbortException will get injected into the thread and as a result it may corrupt critical program data structures you did not anticipate.
Use the new cooperative cancellation mechanisms included with the TPL. Change the while (true) loop to poll a CancellationToken instead. Signal the cancellation in the Dispose method when you implement IDisposable. Do not include a finalizer (destructor in C# terminology). Finalizers are intended to be used to clean up unmanaged resources. Since you have not indicated that unmanaged resources are in play then it is pointless to have a finalizer. You do not have to include a finalizer when implementing IDisposable. In fact, it is considered bad practice to have one when it is not really needed.
public class Class : IDisposable
{
private Task task;
private CancellationTokenSource cts = new CancellationTokenSource();
Class()
{
task = new Task(Run, cts.Token, TaskCreationOptions.LongRunning);
task.Start();
}
public void Dispose()
{
cts.Cancel();
}
private void Run()
{
while (!cts.Token.IsCancellationRequested)
{
// Your stuff goes here.
}
}
}
If you implement IDisposable, and dispose the object, then the code in Dispose will run, but there is no guarantee that Destructor will also be called.
Garbage Collector forms an opinion that it is a waste of time. So if you want to have a predictable dispose you can use IDisposable.
Check this Thread
Slightly off-topic: You can use Tasks instead of naked threads to run functions without worrying about disposal.
There are multiple issues here:
Setting the variable to null doesn't delete anything, it simply removes a reference to your instance.
The destructor will only get called when the garbage collector decides to collect your instance. The garbage collector runs infrequently, typically only when it detects that there is memory pressure.
The garbage collector collects ONLY orphaned collections. Orphaned means that any references pointed to by your object are invalid.
You should implement the IDisposable interface and call any cleanup code in the Dispose method. C# and VB offer the using keyword to make disposal easier even in the face of exception.
A typical IDisposable implementation is similar to the following:
class MyClass:IDisposable
{
ClassB _otherClass;
...
~MyClass()
{
//Call Dispose from constructor
Dispose(false);
}
public void Dispose()
{
//Call Dispose Explicitly
Dispose(true);
//Tell the GC not call our destructor, we already cleaned the object ourselves
GC.SuppressFinalize(this);
}
protected virtual Dispose(bool disposing)
{
if (disposing)
{
//Clean up MANAGED resources here. These are guaranteed to be INvalid if
//Dispose gets called by the constructor
//Clean this if it is an IDisposable
_otherClass.Dispose();
//Make sure to release our reference
_otherClass=null;
}
//Clean UNMANAGED resources here
}
}
You can then use your class like this :
using(var myClass=new MyClass())
{
...
}
Once the using block terminates, Dispose() will be called even if an exception occurs.
CLR maintains all the running threads. You will have passed the InstanceMethod of your class to the thread's constructor as either ThreadStart or ParameterizedThreadStart delegate. Delegate will hold the MethodInfo of the method you passed and the Instance of your class in Target Property.
Garbage collector collects and object which should not have any Strong References but your instance is still alive inside Delegate of Thread. So your class is still having the Strong Reference hence it is not eligible for garbage collection.
To prove what I stated above
public class Program
{
[STAThread]
static void Main(string[] args)
{
GcTest();
Console.Read();
}
private static void GcTest()
{
Class cls = new Class();
Thread.Sleep(10);
cls = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
public class Class
{
private Thread _thread;
~Class()
{
Console.WriteLine("~Class");
_thread.Abort();
_thread = null;
}
public Class()
{
_thread = new Thread(ThreadProc);
_thread.Start();
}
private void ThreadProc()
{
while (true)
{
Thread.Sleep(10);
}
}
}
}
Try the above code. Destructor Will not be called. To make it work mark the ThreadProc method as static and run again Destructor will be called
Related
Where to call Dispose() for IDisposable objects owned by an object?
public class MyClass
{
public MyClass()
{
log = new EventLog { Source = "MyLogSource", Log = "MyLog" };
FileStream stream = File.Open("MyFile.txt", FileMode.OpenOrCreate);
}
private readonly EventLog log;
private readonly FileStream stream;
// Other members, using the fields above
}
Should I implement Finalize() for this example? What if I do not implement anything at all? Will there be any problems?
My first thought was that MyClass should implement IDisposable. But the following statement in an MSDN article confused me:
Implement IDisposable only if you are using unmanaged resources directly. If your app simply uses an object that implements
IDisposable, don't provide an IDisposable implementation.
Is this statement wrong?
If MyClass owns an IDisposable resource, then MyClass should itself be IDisposable, and it should dispose the encapsulated resource when Dispose() is called on MyClass:
public class MyClass : IDisposable {
// ...
public virtual void Dispose() {
if(stream != null) {
stream.Dispose();
stream = null;
}
if(log != null) {
log.Dispose();
log = null;
}
}
}
No, you should not implement a finalizer here.
Note: an alternative implemention might be something like:
private static void Dispose<T>(ref T obj) where T : class, IDisposable {
if(obj != null) {
try { obj.Dispose(); } catch {}
obj = null;
}
}
public virtual void Dispose() {
Dispose(ref stream);
Dispose(ref log);
}
For objects containing other IDisposable objects, it's a good and recommended practice to implement IDisposable on your own object, so others consuming your type can wrap it in a using statement:
public class MyClass : IDisposable
{
public MyClass()
{
log = new EventLog { Source = "MyLogSource", Log="MyLog" };
FileStream stream = File.Open("MyFile.txt", FileMode.OpenOrCreate);
}
private readonly EventLog log;
private readonly FileStream stream;
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// Free managed objects here
stream.Dispose();
}
}
// Other members, using the fields above
}
In your case, you aren't freeing up any managed resources so no finalizer is needed. If you were, then you would implement a finalizer and call Dispose(false), indicating to your dispose method that it is running from the finalizer thread.
If you don't implement IDisposable, you're leaving it up to the GC to clean up the resources (e.g, close the Handle on the FileStream you've opened) once it kicks in for collection. Lets say your MyClass object is eligible for collection and is currently in generation 1. You would be leaving your FileStream handle open until the GC cleans up the resource once it runs. Also, many implementations of Dispose call GC.SuppressFinalize to avoid having your object live another GC cycle, passing from the Initialization Queue to the F-Reachable queue.
Much of the advice surrounding Dispose and Finalize was written by people who expected Finalize to be workable as a primary resource cleanup mechanism. Experience has shown such expectation to have been overly optimistic. Public-facing objects which acquire any sort of resources and hold them between method calls should implement IDisposable and should not override Finalize. If an object holds any resources which would not otherwise get cleaned up if it was abandoned, it should encapsulate each such resource in a privately-held object which should then use Finalize to clean up that resource if required.
Note that a class should generally not use Finalize to clean up resources held by other objects. If Finalize runs on an object that holds a reference to the other object, one of several conditions will usually apply:
No other reference exists to the other object, and it has already run Finalize, so this object doesn't need to do anything to clean it up.
No other reference exists to the other object, and it hasn't yet run Finalize but is scheduled to do so, so this object doesn't need to do anything to clean it up.
Something else is still using the other object, so this object shouldn't try to clean it up.
The other object's clean-up method cannot be safely run from within the context of a finalizer thread, so this object shouldn't try to clean it up.
This object only became eligible to run Finalize because all necessary cleanup has already been accomplished, so this object doesn't need to do anything to clean things up.
Only define a Finalize method in those cases where one can understand why none of the above conditions apply. Although such cases exist, they are rare, and it's better not to have a Finalize method than to have an inappropriate one.
Say, I have my own C# class defined as such:
public class MyClass
{
public MyClass()
{
//Do the work
}
~MyClass()
{
//Destructor
}
}
And then I create an instance of my class from an ASP.NET project, as such:
if(true)
{
MyClass c = new MyClass();
//Do some work with 'c'
//Shouldn't destructor for 'c' be called here?
}
//Continue on
I'd expect the destructor to be called at the end of the if scope but it never is called. What am I missing?
The equivalent to a C++ destructor is IDisposable and the Dispose() method, often used in a using block.
See http://msdn.microsoft.com/en-us/library/system.idisposable.aspx
What you are calling a destructor is better known as a Finalizer.
Here's how you would use IDisposable. Note that Dispose() is not automatically called; the best you can do is to use using which will cause Dispose() to be called, even if there is an exception within the using block before it reaches the end.
public class MyClass: IDisposable
{
public MyClass()
{
//Do the work
}
public void Dispose()
{
// Clean stuff up.
}
}
Then you could use it like this:
using (MyClass c = new MyClass())
{
// Do some work with 'C'
// Even if there is an exception, c.Dispose() will be called before
// the 'using' block is exited.
}
You can call .Dispose() explicitly yourself if you need to. The only point of using is to automate calling .Dispose() when execution leaves the using block for any reason.
See here for more info: http://msdn.microsoft.com/en-us/library/yh598w02%28v=vs.110%29.aspx
Basically, the using block above is equivalent to:
MyClass c = new MyClass();
try
{
// Do some work with 'C'
}
finally
{
if (c != null)
((IDisposable)c).Dispose();
}
There is no way you can control a timing or make a guess on when actually destructor of the object will be called. It's all up to the Garbage Collector.
The only think you can be sure, in this case, that at the moment you leave that scope the object c becomes unreachable (I assume there are no global references to that instance inside the scope), so the instance c is intended to be identified and removed by Garbage Collector when time comes.
It is up to the garbage collector as to when an object is freed up. However you can force an object to be freed up by calling Finalize. or GC.Collect which will force the garbage collector to take action.
so lets say we have some thing like this websericeclient object
var myname = new WebServiceClient().GetName ( ) ;
what will happen to this object (WebServiceClient()) is it going to dispose automatically or stay in memory .
"Disposing" (calling IDisposable.Dispose()) has nothing to do with memory. It has to do with freeing unmanaged resources like file or database handles.
What happens when you don't call Dispose() is that these resources will remain until the finalizer is called when the Garbage Collector runs to free the object from memory. If you needed those resources (or if something interesting is meant to happen when they are Disposed()) then you don't want to wait some arbitrary period of time - call Dispose() as soon as you're done with it.
It depends on the _GetName()_ method. And on the _WebServiceClient()_.
Let's take the example:
public class WebServiceClient : IDisposable
{
private static WebServiceClient viciousReference = null;
public WebServiceClient()
{
viciousReference = this;
}
~WebServiceClient()
{
Dispose();
}
public void Dispose()
{
// Standard Dispose implementation
}
}
If your object implements Dispose(), always try to call it yourself. Don't only rely on the garbage collector.
In .NET (C#) I follow some custom conventions and patterns that require Constructors, Initialization functions and IDisposable implementations. A typical class is illustrated below. No initialization is done directly in the constructor but rather through a dedicated function that is supposed to make the object reusable. However, I am not sure what happens when Dispose gets called. If the GC calls it, the reference to the object is lost anyways so no worries there. If it is explicitly called, are there any drawbacks simply calling Initialize and treating the class as a fresh object since GC.SupressFinalize has been called? Lol, I'm sure I could have asked this in an easier way.
public abstract class Thread: System.IDisposable
{
protected bool Disposed { get; set; }
protected bool Terminate { get; private set; }
public bool IsRunning { get; private set; }
private System.Threading.Thread ThreadObject { get; set; }
public Thread ()
{
this.Initialize();
}
~Thread ()
{
this.Dispose(false);
}
public virtual void Initialize ()
{
this.Stop();
this.Disposed = false;
this.Terminate = true;
this.IsRunning = false;
this.ThreadObject = null;
}
//====================================================================================================
// Functions: Thread
//====================================================================================================
public void Start ()
{
if (!this.IsRunning)
{
this.IsRunning = true;
this.Terminate = false;
this.ThreadObject = new System.Threading.Thread(new System.Threading.ThreadStart(this.Process));
this.ThreadObject.Start();
}
}
/// <summary>
/// Override this method to do thread processing.
/// [this.Terminate] will be set to indicate that Stop has been called.
/// </summary>
/// <param name="template"></param>
protected abstract void Process ();
public void Stop (System.TimeSpan timeout)
{
if (this.IsRunning)
{
this.Terminate = true;
try
{
if (timeout.TotalMilliseconds > 1D)
{
this.ThreadObject.Join(timeout);
}
else
{
this.ThreadObject.Join();
}
}
catch
{
try
{
this.ThreadObject.Abort();
}
catch
{
}
}
this.ThreadObject = null;
this.IsRunning = false;
}
}
//====================================================================================================
// Interface Implementation: System.IDisposable
//====================================================================================================
public void Dispose ()
{
this.Dispose(true);
System.GC.SuppressFinalize(this);
}
protected virtual void Dispose (bool disposing)
{
if (!this.Disposed)
{
if (disposing)
{
// Dispose managed resources.
this.Stop(System.TimeSpan.FromSeconds(1));
}
// Dispose unmanaged resources here.
// Note disposing has been done.
this.Disposed = true;
}
}
}
The GC never calls Dispose, it's up to the consuming code. The GC does however call the finalizer. This is used in the best practice IDisposable implementation to clean up unmanaged code only.
Where Dispose is used outside of the context of a finalizer, then there is no need for the GC to call the finalizer, and therefore SuppressFinalize is used as an optimisation to prevent it happening twice.
If the object is reused this causes an issue. Technically you can re-register the finalizer on initialization, but this would need to be made thread safe. Common practice is that an object is not reused after it has been Disposed, and typically the Dispose method should only execute exactly once. IMO the initializer method and object reuse introduces complexities to the pattern that move it away from it's intended purpose.
There's no technical reason why you can't reactivate a disposed object in this way, though I woudln't do it as it's against the principle of least surprise (most disposable objects are used once).
If you really do want to go this way, I'd avoid having a finalizer, which means your IDisposable class must not directly own any unmanaged resources. You can do this by wrapping any unmanaged resources your class uses in a manged wrapper (e.g. look at the SafeHandle class for an example).
I don't like all the precise details of your thread handling, but if you are going to have a class where each instance owns a thread, you should provide a Dispose method which will ensure that the instance's thread dies off in an orderly fashion.
If you want to allow for the thread to get cleaned up even when an object is abandoned, you'll probably have to create a wrapper object to which the outside application holds a reference but your thread does not. The Finalize() method for that wrapper object should nudge the thread in such a way that it will die off. The thread could simply poll a flag every few seconds to see if it should exit, or there could be a more sophisticated termination strategy.
I'm confused, though, why Initialize calls Stop()? I would have expected it to call Start().
Wrong language pattern appication sample is used in the code. I clearly see C++ backgroung for the C# code author. Unfortunately C++ coding techniques in not applicable in C# language.
Better not to allow object to get into garbage collector (GC), simply referencing it somewhere else, as in the Singleton pattern, rather that trying to resurrect disposed object, or use Dispose pattern in a language not allowing full control for the garbage collector and memory management, as is to be true, for example, in C++.
Simply, you should not use C++ idioms in C#, but the tips and tricks are:
Interfaces instead of pure virtual functions in C++,
Interface inheritancee instead of multiple class inheritance in C++,
No memory management (use weak references) instead of full controlled object lifetime in C++
Does the following code render the using(...) function/purpose irrelevant?
Would it cause a deficiency in GC performance?
class Program
{
static Dictionary<string , DisposableClass> Disposables
{
get
{
if (disposables == null)
disposables = new Dictionary<string , DisposableClass>();
return disposables;
}
}
static Dictionary<string , DisposableClass> disposables;
static void Main(string[] args)
{
DisposableClass disposable;
using (disposable = new DisposableClass())
{
// do some work
disposable.Name = "SuperDisposable";
Disposables["uniqueID" + Disposables.Count] = disposable;
}
Console.WriteLine("Output: " + Disposables["uniqueID0"].Name);
Console.ReadLine();
}
}
class DisposableClass : IDisposable
{
internal string Name
{
get { return myName; }
set { myName = value; }
}
private string myName;
public void Dispose( )
{
//throw new NotImplementedException();
}
}
Output: SuperDisposable
My understanding of the using(...) function is to immediately coerce disposal of the DisposableClass. Yet within the code block, we are adding the class to a dictionary collection. My understanding is that a class is inherently a reference type. So my experiment was to see what would happen to the disposable object added to a collection in this manner.
In this case DisposableClass is still quite alive. Classes are a reference type - so my assumption then became that the collection is not simply referencing this type, but indeed holding the class as a value. But, that didn't make sense either.
So what is really going on?
EDIT: modified code with output to prove that the object is not dead, as might be suggested by some answers.
2nd EDIT: what this comes down to as I've gone through some more code is this:
public void Dispose( )
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool dispose)
{
if (!isDisposed)
{
if (dispose)
{
// clean up managed objects
}
// clean up unmanaged objects
isDisposed = true;
}
}
~DisposableClass( )
{ Dispose(false); }
Stepping through the code (had a breakpoint at private void Dispose(bool dispose)), where false is passed to the method, it becomes imperative that resources are properly disposed of here. Regardless, the class is still alive, but you are definitely setting yourself up for exceptions. Answers made me more curious...
Disposing an object does not destroy it; it simply tells it to clean up any unmanaged resources it uses as they are no longer needed. In your example, you're creating a disposable object, assigning to a dictionary, and then just telling it to remove some resources.
The correct scenario for the using statement is when you want to initialize a resource, do something with it, and then destroy it and forget about it; for example:
using (var stream = new FileStream("some-file.txt"))
using (var reader = new StreamReader(stream))
{
Console.Write(reader.ReadToEnd());
}
If you want to retain the object after you've used it, you shouldn't be disposing it, and hence a using statement should not be used.
You should not be using a using block in this case, since you need the object after the block has finished. It is only to be used when there is a clear starting and ending point of the lifetime of the object.
It's important to remember that IDisposable, while a slightly special interface, is an interface nonetheless. When the using block exits, it calls Dispose() on your object. Nothing more. Your reference is still valid and, if your Dispose method does nothing, your object will be completely unaffected. If you don't keep track the disposal and explicitly throw exceptions, then you won't get any exceptions after that point because there is no inherent disposed state in .NET.
The IDisposable interface indicates that a type manages some kind of resource. The Dispose method exists to allow you to dispose of the resources used by an instance without having to wait for garbage-collection to take place and the resources to be freed by a finalizer.
In your example, the dictionary is still containing a reference to the disposable class, but the instance will have been disposed at the end of the using block. Subsequent attempts to call methods on the instance will now likely throw ObjectDisposedException or InvalidOperationException, to indicate the instance is no longer in a "working" state.
Disposing an IDisposable is not to be confused with releasing the memory occupied the instance, or invoking any garbage-collection routines on it. The instance is tracked and managed by the garbage-collector like any other, only to be released when the garbage-collector decides it.