I have some code in a WPF application that looks like this:
public class MyTextBox : System.Windows.Controls.TextBox, IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
Dispatcher.BeginInvoke((Action) delegate
{
// do work on member variables on the UI thread.
});
}
~MyTextBox()
{
Dispose(false);
}
}
The dispose method is never getting explicitly called so the destructor calls it. It seems like in this case the object would be destroyed before the delegate in the BeginInvoke fires on the UI thread. It appears to be working though. What is happening here? Is this safe?
It seems like in this case the object would be destroyed before the
delegate in the BeginInvoke fires on the UI thread
The finalizer queues work to the UI message loop. The object may finish running its finalizer method before the actual delegate gets invoked on the UI thread, but that doesn't matter, as the delegate gets queued regardless.
What is happening here?
You're queueing work to the UI from the finalizer.
Is this safe?
Safe is a broad term. Would I do this? Definitely not. It looks and feels weird that you're invoking manipulation of UI elements from a finalizer, especially given this is a TextBox control. I suggest you get the full grasp of what running a finalizer guarantees and doesn't guarantee. For one, running a finalizer doesn't mean the object gets cleaned up in memory right away.
I'd also suggest reading #EricLippert posts: Why everything you know is wrong, Part1 & Part2
When you call BeginInvoke you're adding a delegate to a queue in the dispatcher, and that delegate is going to be pointing to an object that has a reference to the object that Dispose was called on. Since there is a reference to the object accessible through a rooted variable, this object is not eligible for collection.
Now, this is going to be extremely confusing to others using this code, so you should try to avoid "reanimating" objects that have already been finalized if at all possible.
Related
I have:
public static Thread MainThread
{
get { return Thread.CurrentThread; }
}
in my "main" class
I want to do following in other class:
~Class()
{
Program.MainThread.Start(this.Dispose(false));
}
How can I run method in some thread? How can I run GC in main thread?
How can I run CG in main thread?
GC always runs in it's own threads.
How can I run method in some thread?
You can not unless the other thread has an API entry point waiting for things to process (like the UI has where you can invoke into the message pump).
You can't run a method in the thread remotly.
As for GC, so it can work async, it will run in a different thread.
You can't tell the Garbage Collector when to finalize an object or what thread to finalize an object on.
You can tell the Garbage Collector that now would be a good time to collect by calling GC.Collect.
You can tell the Garbage Collector that an object that fully and properly implements IDisposable, does not need to be finalized by calling GC.SuppressFinalize when IDisposable.Dispose is called directly.
Once again, you cannot control when, other than suppressing, or on what thread that an objects finalizer will be run.
Your Finalizer/Destructor and protected Dispose(bool disposing) implementation have to be aware of this limitation and handle cross-thread and null checks appropriately.
Here is example program that exhibits surprising finalization behavior:
class Something
{
public void DoSomething()
{
Console.WriteLine("Doing something");
}
~Something()
{
Console.WriteLine("Called finalizer");
}
}
namespace TestGC
{
class Program
{
static void Main(string[] args)
{
var s = new Something();
s.DoSomething();
GC.Collect();
//GC.WaitForPendingFinalizers();
s.DoSomething();
Console.ReadKey();
}
}
}
If I run the program, what gets printed is:
Doing something
Doing something
Called finalizer
This appears as expected. Because there is a reference to s after the call to GC.Collect(), s is not a garbage.
Now remove comments from the line //GC.WaitForPendingFinalizers();
build and run the program again.
I would expect nothing to change in the output. This because I read that if object is found to be a garbage and it has a finalizer, it will be put on finalizer queue. Since object is not a garbage, then is seems logical that it should not be put on finalizer queue. Thus the line commented out should do nothing.
However, the output of the program is:
Doing something
Called finalizer
Doing something
Can somebody help my understanding of why finalizer gets called?
I can't reproduce the problem on my laptop, but your DoSomething method doesn't use any fields within the object. That means that the object can be finalized even while DoSomething is running.
If you change your code to:
class Something
{
int x = 10;
public void DoSomething()
{
x++;
Console.WriteLine("Doing something");
Console.WriteLine("x = {0}", x);
}
~Something()
{
Console.WriteLine("Called finalizer");
}
}
... then I suspect you will always see DoingSomething printed twice before "Called finalizer" - although the final "x = 12" may be printed after "Called finalizer".
Basically, finalization can be somewhat surprising - I very rarely find myself using it, and would encourage you to avoid finalizers wherever possible.
Jon's answer is of course correct. I would add to it that the C# specification calls out that the compiler and runtime are allowed to (but not required to) notice that the reference contained in a local variable is never again dereferenced, and at that point the garbage collector is allowed to treat the object as dead if the local is the last living reference. Therefore the object can be collected and the finalizer run even though there appears to be a reference in a living local variable. (And similarly the compiler and runtime are allowed to make locals live longer if they so choose.)
Given this fact you can end up in bizarre situations. For example, it is possible for a finalizer to be executing on the finalizer thread while the object's constructor is running on a user thread. If the runtime can determine that "this" is never dereferenced again then the object can be treated as dead the moment the constructor is done mutating fields of "this". If the constructor then does additional work -- say, mutating global state -- then that work can be done as the finalizer is running.
This is just yet another reason why writing a correct finalizer is so difficult that you probably should not do so. In a finalizer everything you know is wrong. Everything you're referring to could be dead, you're on a different thread, the object might not be fully constructed, possibly none of your program invariants are actually maintained.
Your DoSomething() is so trivial that it's likely to get inlined. After it's been inlined, there's nothing that still has a reference to the object, so there's nothing preventing it from being garbage collected.
GC.KeepAlive() is designed specifically for this scenario. It can be used if you want to prevent an object from being garbage collected. It does nothing, but the garbage collector doesn't know that. Call GC.KeepAlive(s); at the end of Main to prevent it from being finalised earlier.
In a library I've created, I have a class, DataPort, that implements functionality similar to the .NET SerialPort class. It talks to some hardware and will raise an event whenever data comes in over that hardware. To implement this behavior, DataPort spins up a thread that is expected to have the same lifetime as the DataPort object. The problem is that when the DataPort goes out of scope, it never gets garbage collected
Now, because DataPort talks to hardware (using pInvoke) and owns some unmanaged resources, it implements IDisposable. When you call Dispose on the object, everything happens correctly. The DataPort gets rid of all of its unmanaged resources and kills the worker thread and goes away. If you just let DataPort go out of scope, however, the garbage collector will never call the finalizer and the DataPort will stay alive in memory forever. I know this is happening for two reasons:
A breakpoint in the finalizer never gets hit
SOS.dll tells me that the DataPort is still alive
Sidebar: Before we go any further, I'll say that yes, I know the answer is "Call Dispose() Dummy!" but I think that even if you let all references go out of scope, the right thing should happen eventually and the garbage collector should get rid of the DataPort
Back to the Issue: Using SOS.dll, I can see that the reason my DataPort isn't being garbage collected is because the thread that it spun up still has a reference to the DataPort object - through the implicit "this" parameter of the instance method that the thread is running. The running worker thread will not be garbage collected, so any references that are in the scope of the running worker thread are also not eligible for garbage collection.
The thread itself runs basically the following code:
public void WorkerThreadMethod(object unused)
{
ManualResetEvent dataReady = pInvoke_SubcribeToEvent(this.nativeHardwareHandle);
for(;;)
{
//Wait here until we have data, or we got a signal to terminate the thread because we're being disposed
int signalIndex = WaitHandle.WaitAny(new WaitHandle[] {this.dataReady, this.closeSignal});
if(signalIndex == 1) //closeSignal is at index 1
{
//We got the close signal. We're being disposed!
return; //This will stop the thread
}
else
{
//Must've been the dataReady signal from the hardware and not the close signal.
this.ProcessDataFromHardware();
dataReady.Reset()
}
}
}
The Dispose method contains the following (relevant) code:
public void Dispose()
{
closeSignal.Set();
workerThread.Join();
}
Because the thread is a gc root and it holds a reference to the DataPort, the DataPort is never eligible for the garbage collection. Because the finalizer is never called, we never send the close signal to the worker thread. Because the worker thread never gets the close signal, it keeps going forever and holding that reference. ACK!
The only answer I can think of to this problem is to get rid of the 'this' parameter on the WorkerThread method (detailed below in the answers). Can anybody else think of another option? There must be a better way to create an object with a thread that has the same lifetime of the object! Alternatively, can this be done without a separate thread? I chose this particular design based on this post over at the msdn forums that describe some of the internal implementation details of the regular .NET serial port class
Update a bit of extra information from the comments:
The thread in question has IsBackground set to true
The unmanaged resources mentioned above don't affect the problem. Even if everything in the example used managed resources, I would still see the same issue
To get rid of the implicit "This" parameter, I changed the worker thread method around a bit and passed in the "this" reference as a parameter:
public static void WorkerThreadMethod(object thisParameter)
{
//Extract the things we need from the parameter passed in (the DataPort)
//dataReady used to be 'this.dataReady' and closeSignal used to be
//'this.closeSignal'
ManualResetEvent dataReady = ((DataPort)thisParameter).dataReady;
WaitHandle closeSignal = ((DataPort)thisParameter).closeSignal;
thisParameter = null; //Forget the reference to the DataPort
for(;;)
{
//Same as before, but without "this" . . .
}
}
Shockingly, this did not solve the problem!
Going back to SOS.dll, I saw that there was still a reference to my DataPort being held by a ThreadHelper object. Apparently when you spin up a worker thread by doing Thread.Start(this);, it creates a private ThreadHelper object with the same lifetime as the thread that holds onto the reference that you passed in to the Start method (I'm inferring). That leaves us with the same problem. Something is holding a reference to DataPort. Let's give this one more try:
//Code that starts the thread:
Thread.Start(new WeakReference(this))
//. . .
public static void WorkerThreadMethod(object weakThisReference)
{
DataPort strongThisReference= (DataPort)((WeakReference)weakThisReference).Target;
//Extract the things we need from the parameter passed in (the DataPort)
ManualResetEvent dataReady = strongThisReferencedataReady;
WaitHandle closeSignal = strongThisReference.closeSignal;
strongThisReference= null; //Forget the reference to the DataPort.
for(;;)
{
//Same as before, but without "this" . . .
}
}
Now we're OK. The ThreadHelper that gets created holds onto a WeakReference, which won't affect garbage collection. We extract only the data we need from the DataPort at the beginning of the worker thread and then intentionally lose all references to the DataPort. This is OK in this application because the parts of it that we grab don't change over the lifetime of the DataPort. Now, when the top level application loses all references to the DataPort, it's eligible for garbage collection. The GC will run the finalizer which will call the Dispose method which will kill the worker thread. Everything is happy.
However, this is a real pain to do (or at least get right)! Is there a better way to make an object that owns a thread with the same lifetime as that object? Alternatively, is there a way to do this without the thread?
Epilogue:
It would be great if instead of having a thread that spends most of its time doing WaitHandle.WaitAny(), you could have some sort of wait handle that didn't need it's own thread, but would fire a continuation on a Threadpool thread once it's triggered. Like, if the hardware DLL could just call a delegate every time there's new data instead of signaling an event, but I don't control that dll.
I believe that the problem is not in the code you have shown but in the code using this serial port wrapper class. If you don't have a "using" statement there, see http://msdn.microsoft.com/en-us/library/yh598w02.aspx, you don't have deterministic cleanup behaviour. Instead, you then rely on the garbage collector but that will never reap an object that is still referenced, and all stack-variables of a thread (whether as normal parameter or this-pointer) count as references.
I have an application with two classes, A and B. The class A has inside a reference to class B. The destructors of the classes do some cleanup of resources but they have to be called in the right order, first the destructor of A and then the destructor of B.
What is happening is that somehow the destructor of B is called first and then the destructor of A is crashing because is trying to execute methods from a disposed object.
Is this behavior of the GC correct? I expected the GC to detect that A has a reference to B and then call the A destructor first. Am I right?
Thanks mates!
PD: In case of doubt about destructor/finalizer/disposer etc that's what we have:
~A()
{
this.Dispose();
}
~B()
{
this.Dispose();
}
As others have noted, your finalizers are wrong, wrong, wrong. You cannot simply call Dispose in a finalizer and expect good things to happen. Read up on the correct way to implement the disposable pattern.
Getting that right is the beginning, not the end, of the work you have to do. In addition to all the other correct answers here, I note that:
the finalizer can (and usually does) run on a different thread. Finalizing resources that have an affinity to a particular thread is dangerous, you can run into deadlocks if you are not careful, and so on.
finalization can "resurrect" a dead object by assigning a reference to it to a variable that is in a live object. Do not do that. It is incredibly confusing.
finalizers can run on objects that were partially constructed when a thread abort exception happened. You cannot assume that any invariant that is true of a fully-constructed object is true of an object being finalized.
Writing a finalizer correctly is extremely difficult for all these reasons. Avoid, avoid, avoid.
The GC is nondeterministic: it is not guaranteed to garbage-collect your objects in any particular order, or at any time, or even ever---it could decide to keep them around after your program is completed, if it wanted to. Thus finalizers are very rarely useful or used.
If you want deterministic finalization, you should use the IDisposable pattern.
From http://msdn.microsoft.com/en-us/magazine/bb985010.aspx:
The runtime doesn't make any guarantees as to the order in which Finalize methods are called. For example, let's say there is an object that contains a pointer to an inner object. The garbage collector has detected that both objects are garbage. Furthermore, say that the inner object's Finalize method gets called first. Now, the outer object's Finalize method is allowed to access the inner object and call methods on it, but the inner object has been finalized and the results may be unpredictable. For this reason, it is strongly recommended that Finalize methods not access any inner, member objects.
You should not write code that depends on the deconstructors in C#, they might never be run so can not be depended upon.
The correct way to write finalizers is to not call anything on related objects, you should only destroy unmanaged resources through the finalizer, precisely because, as you've noted, things happen out of order.
As others have noted, this is documented as part of the specification, so this is not a bug, nor is it something that will change to "do the right thing". In particular, think about two objects both having a reference to the other, it would be impossible for the runtime to figure out what the correct order would be here.
In any case, here's how you should implement a finalizer. Note that you should only implement a finalizer if you need to destroy unmanaged resources (note, there are some edge-cases where you might want a finalizer for a very special-purpose class, but I won't mention these here any more than this):
public class Test : IDisposable
{
~Test()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
// TODO: Make sure calling Dispose twice is safe
if (disposing)
{
// call Dispose method on other objects
GC.SuppressFinalize(this);
}
// destroy unmanaged resources here
}
}
You can find more information here: Implementing a Dispose Method.
I have the following code (cut down for readability):
Main Class:
public StartProcess()
{
Thinker th = new Thinker();
th.DoneThinking += new Thinker.ProcessingFinished(ThinkerFinished);
th.StartThinking();
}
void ThinkerFinished()
{
Console.WriteLine("Thinker finished");
}
Thinker Class:
public class Thinker
{
private System.Timers.Timer t;
public delegate void ProcessingFinished();
public event ProcessingFinished DoneThinking;
BackgroundWorker backgroundThread;
public Thinker() { }
public StartThinking()
{
t = new System.Timers.Timer(5000); // 5 second timer
t.AutoReset = false;
t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
t.Start();
// start a background thread to do the thinking
backgroundThread = new BackgroundWorker();
backgroundThread.DoWork += new DoWorkEventHandler(BgThread_DoWork);
backgroundThread.RunWorkerAsync();
}
void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
DoneThinking();
}
BgThread_DoWork(object sender, DoWorkEventArgs e)
{
// work in here should go for much less than 5 seconds
// it will die if it doesn't
t.Stop();
DoneThinking();
}
}
What I originally expected to happen was that the event handler in the main class would prevent the Thinker from being garbage collected.
Apparently this isn't the case.
I'm now wondering whether garbage collection will occur regardless of whether this thread is "busy" or not. In other words, is there a chance it will be garbage collected before the 5 second timeout has expired?
To put it another way, is it possible for the garbage collector to collect my Thinker before it's finished processing?
No, a thread is considered live as long as it is referenced, and any thread that is running is considered to be referenced (IIRC a running thread registers its stack as a GC root, and that stack will reference the thread).
That said i'm looking at your example and i don't understand where you believe a thread is being spawned?
No, a running thread's stack acts as a root for GC purposes. That stack will live as long as the Thread is running, so the Thread itself won't be collected as long its running.
Here's an article that mentions (among other things) what the roots are for GC purposes. To save some time, GC roots are global objects, static objects, all reference on all thread stacks, and all CPU registers containing references.
Your question is a little difficult to answer. Like Joel, as far as I can tell, you have nothing on the stack referencing your timer, which itself is the only thing referencing the thread. Given that, one would expect the Thinker instance would be collected.
I was curious about this, and needed a more concrete explanation of what might happen, so I dug into Reflector a bit. As it turns out, System.Timers.Timer ultimately creates a System.Threading.Timer, which internally creates an instance of TimerBase, an internal class. TimerBase derives from CriticalFinalizerObject, which is a system type that ensures that all code in a Constrained Execution Region (CER) will execute before the implementing class is fully finalized and discarded by the GC. TimerBase is also IDisposable, and its dispose method loops and spinwaits until a lock is released. At this point, I started running into external code, so I am not exactly sure how the lock is initialized or released.
However, based on how the TimerBase class is written, the fact that it derives from CriticalFinalizerObject, and the fact that its dispose spinwaits until a lock is released, I think its safe to say that a thread that is not referenced by anything will not be finalized until that code is done executing. That said...it is important to note that it quite likely will be processed by the GC...quite possibly more than once, as finalization can greatly lengthen the process of collection on finalized objects. For those that are CriticalFinalizerObjects, the finalization process could take even longer if there is actively executing code that the CER is ensuring will fully execute.
That could mean you have exactly the opposite problem if your Thinkers take a while to execute. Rather than those objects being collected prematurely, they will go into a lengthy finalization, and anything they reference ending up in gen2, and living for quite some time until the GC is finally able to fully collect them.
If I'm reading this right (and I could be way off here), it can be collected because it's not currently doing anything.
If you had local variables in your start method, and that method was still active, those variables would still be "in scope" on the stack and provide a root for your thread. But the only variable you use is your private timer, and since that is rooted with the thread itself and the thread has nothing on the stack, there's nothing left to keep it alive.
I agree and disagree, If the reference to the thread object is lost the thread will be terminated and garbage collected. In your case it might not be as such because it is not directly using threads and is using timer. But if you had called a method in a thread and the thread reference was lost with the end of the method then it would be collected by GC