n00b question about destructors

G

gabest

I've got the following situation, simplified example of course. The
thread would be deep behind interfaces, classes, etc. Is there any way
to automagically exit it without having to add an Exit() call to
everywhere? I just want to break that loop when the application is
done (the thread is still running so it cannot be done, but I think
there is no more reference from the root object, so it could call the
destructor at least), or when the object containing this thread is
collected by the GC. Apparently, it never happens now.

class Program
{
static void Main(string[] args)
{
Program p = new Program();
}

private volatile bool _exit;

public Program()
{
_exit = false;

Thread _thread = new Thread(ThreadProc);

_thread.Start();
}

~Program()
{
_exit = true;
}

void ThreadProc()
{
while(!_exit)
{
Thread.Sleep(1);
}
}
}
 
C

Christof Nordiek

First of all, you can't use 'destructors' for this. Actually there are no
destrucktors in C# but finalizers. The originally were called destructors,
but they have very different semantics then destructors in e.g. C++.
Finalizers are called by the GC and can't be called deterministcally.
Instead, you should use a method Abort or similar for this use.

You can call _thread.Abort(), wich will terminiate the thread. But that can
have very bad side effects, since the abortion can occur on any place in the
thread code. You're way (besides the wring use of finalizer) actually is the
recommended.

Christof
 
G

gabest

You can call _thread.Abort(), wich will terminiate the thread. But that can
have very bad side effects, since the abortion can occur on any place in the
thread code. You're way (besides the wring use of finalizer) actually is the
recommended.

I could even flip that _exit to true and then it would exit cleanly,
but this is running inside a class which is used through an interface
which doesn't have a call something like Shutdown().

On msdn I found the following. It suggests that at least in some cases
the destructor is called. I don't really care when, just once would be
great, to let the application exit :)

"The programmer has no control over when the destructor is called
because this is determined by the garbage collector. The garbage
collector checks for objects that are no longer being used by the
application. If it considers an object eligible for destruction, it
calls the destructor (if any) and reclaims the memory used to store
the object. Destructors are also called when the program exits."
 
K

ktrvnbq02

I could even flip that _exit to true and then it would exit cleanly,
but this is running inside a class which is used through an interface
which doesn't have a call something like Shutdown().

On msdn I found the following. It suggests that at least in some cases
the destructor is called. I don't really care when, just once would be
great, to let the application exit :)

[snip]

Do you actually need to have the thread self-terminate and run clean-
up, or are you just trying to make sure your application is able to
exit regardless of whether the thread is still running? If it's the
latter, set the IsBackground property of the thread to ensure it
doesn't prevent the process from terminating.


Matt
 
C

Christof Nordiek

"The programmer has no control over when the destructor is called
because this is determined by the garbage collector. The garbage
collector checks for objects that are no longer being used by the
application. If it considers an object eligible for destruction, it
calls the destructor (if any) and reclaims the memory used to store
the object. Destructors are also called when the program exits."
This still wouldn't help in your case, because the object would'nt be
eligible for destruction/finalizaition before the thread ends. The thread
method is an instance method of the said object, and refers to the instance
field _exit. By this, it holds the object living.

Christof
 
G

gabest

Do you actually need to have the thread self-terminate and run clean-
up, or are you just trying to make sure your application is able to
exit regardless of whether the thread is still running? If it's the
latter, set the IsBackground property of the thread to ensure it
doesn't prevent the process from terminating.

In the end I solved it a different way, but I'll keep that in mind,
with IsBackground the process quits in the example. What I was really
trying to do was a scheduler thread to signal events at queued times.
Accuracy is another question, I found nothing better than calling
winmm.dll's time functions for 1ms precision.
 
G

gabest

This still wouldn't help in your case, because the object would'nt be
eligible for destruction/finalizaition before the thread ends. The thread
method is an instance method of the said object, and refers to the instance
field _exit. By this, it holds the object living.

Hmmm, but that object is not referenced by anything anymore. I thought
having a root object was the reason circular references can be cleaned
up in .net. The object which references the the _exit field and
spawned the thread was released at the end of the Main function, I
fail to see why the destructor cannot be called then.
 
G

gabest

lol, I just put a breakpoint inside the desctructor with IsBackground
= true and it stopped there. So, there is a clean way to release this
object afterall. (?)
 
G

Gabest

lol, I just put a breakpoint inside the desctructor with IsBackground
= true and it stopped there. So, there is a clean way to release this
object afterall. (?)

Nope, the thread never wakes up while or after the destructor runs,
_exit = true has no effect.
 
C

Christof Nordiek

lol, I just put a breakpoint inside the desctructor with IsBackground
= true and it stopped there. So, there is a clean way to release this
object afterall. (?)

Yes, but because your working thread stopped before. Since you set
IsBackground = true (I suppose, this is on the working thread), the
application shuts down, when the main thread ends. Then the object becomes
eligible for destruction.
But if I understand your OP-code right, you wanted the destructor/finalizer
to stop the thread. That is not possible, if the thread references the
instance (and it does this by accessing _exit, wich actually is this._exit.)
So, the finalizer runs, but doesn't do what you expect.

Christof
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top