From: Arne Vajhøj on
On 09-05-2010 13:27, Tony Johansson wrote:
> Below is a really simple Thread example.
> If I run this example in debug mode and set a breakpoint in the SimpleWork
> why is not this row called immediately when this statement
> theThread.Start(); is executed.
> I have noticed that it is called first when I leave the main method
>
> I have tested several thing when this breakpoint in SimpleWork is hit
> 1. If I for example add a read in the main then as soon as this read has
> been executed this breakpoint in SimpleWork is hit
> 2. If I for example add a sleep on the main thread in main then this
> breakpoint in SimpleWork is hit as soon as this sleep is executing
> 3.If I for example add a WriteLine in the main then as soon as this
> WriteLine has been executed this breakpoint in SimpleWork is hit. This
> happen even if I have some other statement after this WriteLine.
>
> So my question is just what is it that cause the SimpleWork to be called. I
> mean in example 1 I have to leave the main method before the SimpleWork was
> called but in 2 I had to execute a readLine before the SimpleWork was called
> and in exemple 3 I had to execute a WriteLine before the SimpleWork was hit
>
> public static void Main()
> {
> ThreadStart operation = new ThreadStart(SimpleWork);
> Thread theThread = new Thread(operation);
> theThread.Start();
> }
>
> private static void SimpleWork()
> {
> Console.WriteLine("Thread: {0}", Thread.CurrentThread.ManagedThreadId);
> }

SimpleWork gets called some time after theThread.Start() has been
executed.

You should not make any assumptions about exactly when.

It is not particular surprising if the main thread keeps
the CPU for some time if it wants but the new thread
gets the CPU if the main thread is waiting for IO.

But if you need guarantees about how two threads will run,
then you need to do some synchronization between them.

Arne

From: Rick Lones on
Tony Johansson wrote:
> Hi!
>
> Below is a really simple Thread example.
> If I run this example in debug mode and set a breakpoint in the SimpleWork
> why is not this row called immediately when this statement
> theThread.Start(); is executed.
> I have noticed that it is called first when I leave the main method
>
> I have tested several thing when this breakpoint in SimpleWork is hit
> 1. If I for example add a read in the main then as soon as this read has
> been executed this breakpoint in SimpleWork is hit
> 2. If I for example add a sleep on the main thread in main then this
> breakpoint in SimpleWork is hit as soon as this sleep is executing
> 3.If I for example add a WriteLine in the main then as soon as this
> WriteLine has been executed this breakpoint in SimpleWork is hit. This
> happen even if I have some other statement after this WriteLine.
>
> So my question is just what is it that cause the SimpleWork to be called. I
> mean in example 1 I have to leave the main method before the SimpleWork was
> called but in 2 I had to execute a readLine before the SimpleWork was called
> and in exemple 3 I had to execute a WriteLine before the SimpleWork was hit
>
> public static void Main()
> {
> ThreadStart operation = new ThreadStart(SimpleWork);
> Thread theThread = new Thread(operation);
> theThread.Start();
> }
>
> private static void SimpleWork()
> {
> Console.WriteLine("Thread: {0}", Thread.CurrentThread.ManagedThreadId);
> }


My somewhat simplified answer would be that Thread.Start() is the application's
way of informing the underlying runtime that the newly-created thread can now be
scheduled for execution. But that does not cause execution to begin immediately
- the thread must still make its way through the OS's scheduling algorithm
before it can be assigned to a CPU and actually executed. I would think of
ThreadStart() as causing the thread's state to change from "suspended" to
"ready" and for it to therefore be placed on the operating system scheduler's
ready queue.

In all the cases you cite (ReadLine(), etc.): Following ThreadStart() with a
call which causes the current thread to block on I/O or a timer causes the OS
scheduler to suspend your Main() thread while it awaits an external event, thus
giving other threads and processes a chance to use the CPU. Your newly created
thread will then typically get a chance to run before your main thread becomes
ready again. What you are observing is exactly what you should expect when you
make a blocking call.

It's normal when learning a language to develop, e.g., a "c#.net" mental model
of the computer where you begin to think of it (the whole PC) as merely a c#
execution engine and you kind of tune out the rest of it. Usually this is not a
problem, but when you start dealing with threads you really need a somewhat more
inclusive model so as to be able to keep track of what is really going on. In
the absence of that threads can be very baffling (and dangerous!) indeed.

HTH,
-rick-