Re: Thread.Sleep vs Thread.Join
- From: "Willy Denoyette [MVP]" <willy.denoyette@xxxxxxxxxx>
- Date: Tue, 21 Mar 2006 11:57:39 +0100
"Joe" <joeusenet@xxxxxxxxx> wrote in message
news:1142902530.953063.284660@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
| I've played around more and found that windows timers behave
| differently when blocked on a sleep vs join. In the program below,
| left-clicking once pauses 5 seconds then starts adding items to the
| listbox, while right-clicking pauses 5 seconds then adds 5 items to the
| listbox (all with the current time). In other words, timer events queue
| up while blocked on a Join, but not while blocked on Sleep.
|
There is no message pumping/dispatching while the UI thread is 'Sleeping'.
On the other end, when you call Join on the current thread you still pump
messages, that means that your Timer messages are getting dispatched when
they arrive, the only thing that's not been handled are the painting
messages, that's why the list is only repainted after the Join time-out
period.
| using System;
| using System.Windows.Forms;
|
| class SleepJoinForm : Form
| {
| Timer tmr = new Timer ();
| ListBox lb = new ListBox ();
|
| public SleepJoinForm ()
| {
| tmr.Interval = 1000;
| tmr.Tick += delegate { lb.Items.Add (DateTime.Now); };
|
| lb.Dock = DockStyle.Fill;
| Controls.Add (lb);
| lb.MouseDown += delegate (object sender, MouseEventArgs e)
| {
| tmr.Start ();
| if (e.Button == MouseButtons.Left)
| System.Threading.Thread.Sleep (5000);
| else
| System.Threading.Thread.CurrentThread.Join (5000);
| };
| }
|
| [STAThread]
| static void Main () { Application.Run (new SleepJoinForm ()); }
| }
|
| Interestingly if you replace STAThread with MTAThread, the Join-wait
| behaves just like the Sleep-wait. I think you're right in that it's
| related to message pumping.
|
| I wonder if it's possible for a similar issue to crop up in a non-UI
| application? Unfortunately I'm largely ignorant of COM and message
| pumping.
|
That's what I said in my previous response, the CLR pumps the queue only
when Join is called on a STA thread, otherwise it behaves 'like' a Sleep.
You see there are two pre-requisites, you need a thread with a message queue
that runs in a STA. All UI threads have a message queue and they should run
in a STA, a non UI thread that hosts a apartment threaded COM object, must
run in a STA AND MUST pump the message queue. The CLR performs a (limited)
pumping wait when one of the following API's; Monitor.Enter (lock in C#),
Thread.Join, WaitOne, GC.WaitForPendingFinalizers are called from a STA
thread that has a message queue (a window really) attached.
A non UI STA thread that creates an instance of COM object MUST pump the
message queue. Failing to pump, will block the finalizer thread when one
releases the reference to the COM object(s). That means that at least you
should call WaitForPendingFinalizers after you released the Object
reference.
Willy.
.
- Follow-Ups:
- Re: Thread.Sleep vs Thread.Join
- From: Joe
- Re: Thread.Sleep vs Thread.Join
- References:
- Thread.Sleep vs Thread.Join
- From: Joe
- Re: Thread.Sleep vs Thread.Join
- From: Willy Denoyette [MVP]
- Re: Thread.Sleep vs Thread.Join
- From: Joe
- Thread.Sleep vs Thread.Join
- Prev by Date: Re: strategy of migration to VS 2005
- Next by Date: Interfacing with a database using an API
- Previous by thread: Re: Thread.Sleep vs Thread.Join
- Next by thread: Re: Thread.Sleep vs Thread.Join
- Index(es):
Relevant Pages
|