I have an object that contains a working thread. I'd like to kill the thread when the object is out of scope.
using System.IO;
using System;
using System.Threading;
namespace tt {
class Program
{
static void Main()
{
AnotherClass a = new AnotherClass();
a.Say();
}
}
class AnotherClass:IDisposable {
private bool m_Disposed;
private readonly AutoResetEvent m_ResetEvent = new AutoResetEvent(false);
public AnotherClass() {
Thread t = new Thread(wait);
t.Start();
}
public void Dispose() {
Dispose(true);
}
private void Dispose(bool disposing) {
if (m_Disposed) {
return;
}
if (disposing) {
Console.WriteLine("inner disposing");
}
m_ResetEvent.Set();
Console.WriteLine("Outer disposing");
m_Disposed = true;
}
private void wait() {
m_ResetEvent.WaitOne();
}
~AnotherClass() {
Dispose(false);
}
public void Say() {
Console.WriteLine("HellO");
}
}
}
The program will just hang in there because the destructor of AnotherClass is not called. I know I can call a.Dispose() to kill the thread. But is there a way to implicitly kill the thread when the object goes out of scope?
No, that's not possible. There is no reference counting that can notice that the object has no more references, so there is no way to do anything when that happens.
The IDisposable
interface is used for classes that needs to do something when an instance is not going to be used any more, and calling the Dispose
method is how you signal that you are done with the instance.
The usual way to make sure that an object is disposed when you leave a scope is to wrap the code in a using
block:
static void Main()
{
using (AnotherClass a = new AnotherClass())
{
a.Say();
}
}
The using
block is syntactic sugar for a try...finally
block:
static void Main()
{
AnotherClass a = new AnotherClass();
try
{
a.Say();
}
finally
{
if (a != null)
{
((Idisposable)a).Dispose();
}
}
}
Adding to Guffa's answer, I think it's also important to note that even if you had a way to detect the precise moment that your AnotherClass
instance went out out scope, in this case, it just never will. And that's why you noticed that your destructor never got called.
The reason for that is that when you create and start your working thread, the thread is passed a delegate reference pointing to the instance method wait()
which comes with an implicit reference to this
(the AnotherClass
instance). So as long as your thread does not itself go out of scope, it will hold a strong reference to the AnotherClass
instance and prevent it from getting garbage collected.
You could use exception handling and use the error displayed as the exception in the catch block
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With