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.
Related
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.
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 a C# application code in which I use a mutex to synchronise some code during the creation of an object. The object constructor acquires the mutex and ONLY releases it when the object is no longer needed (during app shutdown). Thus one place to release the mutex would be in the object destructor. The problem that arose is that sometimes I got an exception during the call to ReleaseMutex() in the object destructor. The exception is: "Object synchronization method was called from an unsynchronized block of code". It appears that the thread that does gabage collection which calls the object destructor sometimes is not the same thread that waits for the mutex (Mutex.WaitOne(false, namedMutex)) in the first place. How do I syncrhonize the acquire and release of the mutex on the same thread to avert this exception? Thanks for your help!
public class MyObject
{
static ExtDeviceDriver devDrv;
private Mutex mut = new Mutex(false,myMutex);
public MyObject()
{
mut.WaitOne();
//Thread safe code here.
devDrv = new ExtDeviceDriver();
}
~MyObject()
{
mut.ReleaseMutex();
}
}
Why don't you use the Dispose pattern? Mutex inherits from WaitHandle and WaitHandle implements IDisposable. If you have a class that creates and uses an IDisposable it should also implement IDisposable and properly be disposed of. Don't let the GC dispose of your mutex for you, manually do it in a using block or manually call .Dispose() on it. This way you can always know who is doing what and when.
This post has a great quote that you should take to heart:
If the object implements IDisposable then you should think about how the object is getting cleaned up.
Objects that implement IDisposable usually do so because they are holding on to real resources that should be freed deterministically.
Which is exactly what is happening here.
Also I see you are using a named mutex. Named mutexes are used across processes and are managed as operating system handles. Is anyone else acquiring the same mutex and trying to release it? Is there a reason you need a named mutex? These are usually tricky to deal with because you can have abandanded mutexes and all sorts of other weird stuff if the process dies and the mutex isn't gracefully handled.
I ran the following code and found that finalizer is always called. But many articles said that finalizer is non-desterministic.
class Test
{
Test()
{
throw new Exception();
}
~Test()
{
Console.WriteLine("Finalizer is called");
}
static void Main()
{
try
{
new Test();
}
catch { }
}
It is still non-deterministic in your case. Non-deterministic means the amount of time it takes for something to happen cannot be pre-calculated. Note that being unable to correctly determine when something will happen does not necessarily mean random-time but in most cases they are roughly the same.
People who never have to control car brakes, industrial robots or the space shuttle generally should not care weather a piece of code is deterministic or not.
note: I have written code to control industrial robots so I sometimes need to care about my code being executed at the exact moment I want it to be.
The garbage collector calls the finalizer when it collects the object. You can suppress the finalizer call by calling GC.SuppressFinalize(); Documentation
You could place this call inside Dispose() to stop the garbage collector from collecting the class after its resources have been disposed.
In your case, the finalizer is running as part of application shutdown. From the docs:
During shutdown of an application
domain, Finalize is automatically
called on objects that are not exempt
from finalization, even those that are
still accessible.
Non-deterministic refers to when Finalize will be called. But except in exceptional cases (like power being cut off or the process being abruptly killed), the finalizer will eventually be called.
There are cases when it may not be called; and cases where even if it is called, it may not be allowed to complete.
While there are certain occasions when the finalizer will not be called, it will typically be called. The big issue is when it is called, hence it is non-deterministic.
C# is garbage-collected and the garbage collector runs at unspecified intervals. Therefore, if the finalizer needs to do something time-sensitive, it is best to use Dispose instead of a finalizer. For example, you might want to close a database connection immediately instead of leaving it open while waiting for the garbage collector.
That code is so simple that the .NET Runtime can run the finalizer with out problems but in high load applications the Finalizers are only called when garbage collection runs.
There is here an extract of this article
http://msdn.microsoft.com/en-us/magazine/bb985010.aspx
Finalization
The garbage collector offers an additional feature that you may want to take advantage of: finalization. Finalization allows a resource to gracefully clean up after itself when it is being collected. By using finalization, a resource representing a file or network connection is able to clean itself up properly when the garbage collector decides to free the resource's memory.
Here is an oversimplification of what happens: when the garbage collector detects that an object is garbage, the garbage collector calls the object's Finalize method (if it exists) and then the object's memory is reclaimed. For example, let's say you have the following type (in C#):
public class BaseObj {
BaseObj() {}
protected override void Finalize() {
// Perform resource cleanup code here...
// Example: Close file/Close network connection
Console.WriteLine("In Finalize.");
}
}
Now you can create an instance of this object by calling:
BaseObj bo = new BaseObj();
Some time in the future, the garbage collector will determine that this object is garbage. When that happens, the garbage collector will see that the type has a Finalize method and will call the method, causing "In Finalize" to appear in the console window and reclaiming the memory block used by this object.
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