Threading problem
am 11.04.2008 16:25:39 von Davor Dundovic
I'm developing one small "windows application" in C# (Visual Studio
2005) and I have a couple of questions ...
Startup form creates an instance of one of my classes. That instance
creates a new thread which has an endless loop.
1.
If I just close the form (mouse click on "X" for instance), process is
left hanging.
Why doesn't it get collected by garbage collector ?
2.
If I execute Thread.Abort() and then close the form - same thing
happens.
Why doesn't it get collected by garbage collector ?
3.
If I execute Thread.Abort() and Thread.Join() and then close the form
- everything is OK. No orphan processes are left hanging.
So I made destructor in my class that does exactly this.
If I just close the form, the destructor in my class doesn't get
called.
Why ?
4.
If I execute Thread.Abort() and Thread.Join() and then attempt to
close the form, destructor gets called ?!?
Why didn't it got called in section 3. ?
I hope someone will have good will and knowledge to answer my
questions. ;-)
Regards, Dundo.
--
Pozdrav, Dundo.
email: davor dot dundovic at gmail dot com
Re: Threading problem
am 11.04.2008 16:33:40 von Marc Gravell
OK - there isn't really enough information there to give a complete
answer, but some thoughts:
* the second thread: did you set IsBackground = true?
* it is bad practice to call Thread.Abort(); it would be preferable to
toggle a flag somewhere (even a volatile bool would do) that the other
thread checks periodically, and gracefully exits
* how are you showing your main form? form.Show(), form.ShowDialog(),
or Application.Run(form)? The reason I ask is that a form that is
shown modally (ShowDialog) doesn't get Dispose()d automatically
* can't really comment on the abort/join oddities without something
demonstrable...
Marc
Re: Threading problem
am 11.04.2008 17:03:37 von skeet
On Apr 11, 7:25=A0am, Davor Dundovic wrote:
> I'm developing one small "windows application" in C# (Visual Studio
> 2005) and I have a couple of questions ...
>
> Startup form creates an instance of one of my classes. That instance
> creates a new thread which has an endless loop.
>
> 1.
>
> If I just close the form (mouse click on "X" for instance), process is
> left hanging.
>
> Why doesn't it get collected by garbage collector ?
The garbage collector deals with objects, not processes. The process
will exit when there are no non-background threads left running. My
guess is that your new thread isn't a background thread.
> 2.
>
> If I execute Thread.Abort() and then close the form - same thing
> happens.
In that case it sounds like another thread may be involved somewhere.
Break into your code in the debugger and see which threads are still
running.
> Why doesn't it get collected by garbage collector ?
Again, the garbage collector really isn't involved here.
> 3.
>
> If I execute Thread.Abort() and Thread.Join() and then close the form
> - everything is OK. No orphan processes are left hanging.
That sounds pretty odd. As Marc said, Thread.Abort should be avoided
anyway. See
http://pobox.com/~skeet/csharp/threads/shutdown.shtml
> So I made destructor in my class that does exactly this.
Using a finalizer is generally a bad idea. They act extremely non-
deterministically. Combining them with threads (which can also be hard
to reason about) sounds like a very, very bad idea.
> If I just close the form, the destructor in my class doesn't get
> called.
>
> Why ?
Does your other thread have an active reference to the form?
> 4.
>
> If I execute Thread.Abort() and Thread.Join() and then attempt to
> close the form, destructor gets called ?!?
>
> Why didn't it got called in section 3. ?
Presumably my guess was right about the code in the other thread
having a reference to the form.
> I hope someone will have good will and knowledge to answer my
> questions. =A0;-)
A short but complete program demonstrating the problem would really
help.
See http://pobox.com/~skeet/csharp/complete.html
Jon
Re: Threading problem
am 11.04.2008 17:06:14 von Davor Dundovic
On Fri, 11 Apr 2008 07:33:40 -0700 (PDT), Marc Gravell
wrote:
>* the second thread: did you set IsBackground = true?
That's it !
That was quick and helpfull answer ! Thnx !
Now I set it to true and it works fine.
>* it is bad practice to call Thread.Abort(); it would be preferable to
>toggle a flag somewhere (even a volatile bool would do) that the other
>thread checks periodically, and gracefully exits
I've read that but I have a blocking call (UdpClient.Receive) in that
thread so I can't check the state of some flag.
Of course, I could do it asynchroniously (BeginReceive/EndReceive) but
I'm bit lazy ...
>* how are you showing your main form? form.Show(), form.ShowDialog(),
>or Application.Run(form)? The reason I ask is that a form that is
>shown modally (ShowDialog) doesn't get Dispose()d automatically
Application.Run(new Form1());
>* can't really comment on the abort/join oddities without something
>demonstrable...
OK, now it's obvoius that thread was running in foreground and as such
prevented application to terminate.
--
Pozdrav, Dundo.
email: davor dot dundovic at gmail dot com
Re: Threading problem
am 11.04.2008 17:26:48 von Davor Dundovic
On Fri, 11 Apr 2008 08:03:37 -0700 (PDT), "Jon Skeet [C# MVP]"
wrote:
>The garbage collector deals with objects, not processes. The process
>will exit when there are no non-background threads left running. My
>guess is that your new thread isn't a background thread.
I thought since thread is an object it would be collected too.
Anyway, thread was a foreground one. That was the problem.
Now I've set it to be a background and it works fine.
>> If I execute Thread.Abort() and Thread.Join() and then close the form
>> - everything is OK. No orphan processes are left hanging.
>
>That sounds pretty odd. As Marc said, Thread.Abort should be avoided
>anyway. See
How would you break from a thread that is block by a blocked call ?
That is the situation I have.
I could use async calls but didn't want to.
>Does your other thread have an active reference to the form?
No it doesn't but it's a part of that class and since it won't
terminate (foreground thread) I suppose GC doesn't try to collect that
class.
Thnx !
--
Pozdrav, Dundo.
email: davor dot dundovic at gmail dot com
Re: Threading problem
am 11.04.2008 18:42:12 von skeet
On Apr 11, 8:26 am, Davor Dundovic wrote:
> wrote:
> >The garbage collector deals with objects, not processes. The process
> >will exit when there are no non-background threads left running. My
> >guess is that your new thread isn't a background thread.
>
> I thought since thread is an object it would be collected too.
There's an object providing a representation of the thread, but the
thread itself isn't an object. It's like a file - just because a
FileInfo may be garbage collected doesn't mean the file is deleted.
> Anyway, thread was a foreground one. That was the problem.
>
> Now I've set it to be a background and it works fine.
Right.
> >> If I execute Thread.Abort() and Thread.Join() and then close the form
> >> - everything is OK. No orphan processes are left hanging.
>
> >That sounds pretty odd. As Marc said, Thread.Abort should be avoided
> >anyway. See
>
> How would you break from a thread that is block by a blocked call ?
If I want to shut down the process, I'd make sure that the thread is a
background thread. Otherwise, I'd either avoid blocking calls, or just
let the thread wait.
> That is the situation I have.
>
> I could use async calls but didn't want to.
Making things block gives the penalty of not always being able to shut
things down quickly, basically.
> >Does your other thread have an active reference to the form?
>
> No it doesn't but it's a part of that class and since it won't
> terminate (foreground thread) I suppose GC doesn't try to collect that
> class.
If it's part of that class then it does have an active reference - the
implicit "this" reference.
Jon