Why do ManagedThreadId start counting from 3

T

Tony Johansson

Hello!

If I run the program below will the ManagedThreadId start counting from 3 so
the output in SimpleWork is like this.
So why will the ManagedThreadId start counting from 3 ?
Thread: 3
Thread: 4
Thread: 5
Thread: 3
Thread: 4
Thread: 5
Thread: 3
Thread: 4
Thread: 5
Thread: 3
Thread: 4
Thread: 5
Thread: 3
Thread: 4
Thread: 5
Thread: 3
Thread: 4
Thread: 5
Thread: 3
Thread: 4
Thread: 5
Thread: 3
Thread: 4
Thread: 5
Thread: 3
Thread: 4
Thread: 5

static void Main(string[] args)
{
ThreadStart operation = new ThreadStart(SimpleWork);
for (int x = 1; x <= 3; x++)
{
Thread theThread = new Thread(operation);
theThread.Start();
}
}

private static void SimpleWork()
{
for (int x = 1; x <= 10; x++)
{
Console.WriteLine("Thread: {0}",
Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(10);
}
}

//Tony
 
P

Peter Duniho

Tony said:
Hello!

If I run the program below will the ManagedThreadId start counting from 3 so
the output in SimpleWork is like this.
So why will the ManagedThreadId start counting from 3 ?

Hint: the threads you created aren't the only threads in your process.
In fact, you can't create a new thread unless there's already at least
one running. And in actuality, .NET creates other threads for its own
use before your own code gets a chance to start creating new ones.

But beyond all that, there is absolutely no guarantee whatsoever that
the ManagedThreadId property is anything other than a unique identifier
for a Thread instance. It may be interesting in an academic sort of way
to note that the numbers appear to be assigned incrementally, but for
all .NET promises you, they could be completely random.

Asking why the ManagedThreadId property values don't fit your particular
expectation of ordering, initialization, or whatever makes no sense.
Each Thread instance can have any ManagedThreadId .NET wants it to have,
so long as no other Thread instance has that ManagedThreadId.

Pete
 
A

Arne Vajhøj

If I run the program below will the ManagedThreadId start counting from 3 so
the output in SimpleWork is like this.
So why will the ManagedThreadId start counting from 3 ?
Thread: 3
Thread: 4
Thread: 5

Maybe one for main thread and one for GC.

Arne
 
K

kndg

Maybe one for main thread and one for GC.

Arne

Hi Arne,

Actually, this had drove me crazy, but since you had mentioned it, I
would like to share my own findings (though not actually related to the
main discussion).
When I read this post, I tried to calculate how many threads a process
had initially created. For a native Win32 console, there is only one
thread which is understandable and for a native window application,
there are two threads created which is also understandable (extra thread
is for the GUI).
For a .Net console application, there are at minimum four threads
created. So, here is my own guess (I couldn't find a source on the
internet to confirm this)

1. Native Win32 thread hosting the CLR
2. CLR (JIT, Assembly Loader and GC?)
3. ? or GC?
4. Primary AppDomain main thread

Actually, at first I thought that the GC would be on the same thread as
the CLR thread and left the third mysteriously unknown (to myself), but
after researching on the internet, I found that the GC is actually
running concurrently and running on their own thread and that fills my
mysterious thirds thread. And since you had mentioned it, it probably
affirms my own guess.

A .Net windows application create one extra thread to service the GUI,
but a .Net WPF appication create a whopping 10 threads total (probably
for marshalling and communicating with native DirectX library).

Application Thread Count
--------------------------------
Native Win32 Console 1
Native Win32 Window 2
..Net Console 4
..Net Window 5
..Net WPF 10

If someone could point out to the correct info or source, I would be
highly appreciated. Is it for my own understanding the internal working
of .Net process.

Regards.
 
K

kndg

[...]
Actually, there's no reason for an unmanaged (native) GUI program to
have more than one thread, assuming _only_ a dependency on the plain
Win32 GUI API. A GUI does not in and of itself imply an additional
thread; typically, the GUI executes in the same thread that the
process's initial entry point used.

Hi Pete,

Thanks for your response.

I had tried compiling it using the simplest code below, but Windows Task
Manager shows it as having two threads.

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
lcCmdLine, int nCmdShow)
{
MessageBox(NULL, "Hi!", "Say Hi", MB_OK);

return 0;
}

I'm no expert in Windows programming using Win32 API and I had already
forgot how to coding it in C, but from the code above, clearly the
MessageBox is called from the main thread which means that this program
should have one thread only. But what the Task Manager reports make me
think that there is something that cause the program to spawn another
thread. Is it because MessageBox function call the COM component behind
the scene? (I'm not familiar at all with COM object).

Do you have an example that show a single threaded GUI program?

[I'm sorry in advance as the above is not related to .Net at all - I'm
just curious...]
A GUI application that uses COM components, especially those that are
free-threaded (i.e. use the multi-threaded apartment) may result in a
new thread started up by COM, because typically COM is initialized in
the main GUI thread as an STA thread. But even that will vary according
to the exact program.

You _might_ also see one or more extra threads if running the process
under a debugger. But that's just an artifact of debugging.


The first thing to understand is that a native thread may or may not be
the same as a managed thread. So when counting threads, it's important
to make sure one is specific about which kind of thread one is talking
about.

For example, in the above list, the "primary AppDomain main thread" is a
managed thread, while the "native Win32 thread hosting the CLR" is by
definition unmanaged.

Beyond that, I would not expect the above list to be accurate even on
..NET implementations where a managed thread corresponds exactly to an
unmanaged thread. In particular, the main thread for the managed process
is as far as I know the same as the main thread for the process. There's
certainly no obvious reason for it not to be, and even running under the
debugger (*), a .NET console app has only one non-worker thread.

(*) where at least one additional thread is created as part of the
hosting mechanism…I did a test with a simple WPF application, which when
debugging had 6 threads without the debugger's host process and 13 with;
running standalone, it had only 5 threads

I'm checking the thread count using the Process class by enumerating the
Threads property. So, it is probably a total of unmanaged and managed
threads. Coupled with the info from Task Manager, and since current
implementation of managed thread in .Net maps directly to unmanaged
thread, I assume the figure I get is correct. When I run a simple WPF
application, initially I got 10 threads, but over the time it reduced to
7 threads and then up back to 8 threads and then down again but never
below than 7. So, I think as you said the 3 threads probably comes from
the thread pool. But that leaves the other two mysterious.
The GC can be run concurrently or not, depending on .NET implementation
and configuration.

Ok, I will check on how to configure that and observe whether the thread
count will be effected or not.
[...]
I don't actually know what all the different threads .NET and its
various components may create on the behalf of the process actually do.
The fact is, it's not something I worry about very much. The exact
thread count for a managed process is even more of an "implementation
detail" than for an unmanaged process, and even the unmanaged process
has some specific scenarios where you might get a thread or two in your
process you didn't explicitly create.

Yes, I agree. I'm just exploring it simply for my own curiosity.

Regards.
 
K

kndg

Well, I can't explain what you're observing. However, when I compile the
above, Task Manager shows the process has having just one thread. As it
does also if I just create a new project using the built-in Win32
project template.

I don't doubt you're seeing a second thread, but whatever that thread
is, it's coming from something other than the basic process stuff that
normally goes on.

Arghh, I should have try this on different computer... Yes, you are
right. They are all just shows as one thread (XP/Vista/Win7). Hmm...
probably it is just the problem with my system. My first thought was
trojan, but a quick debugging session tells me unlikely (the second
thread just make harmless (probably) calls to the system library).

Anyway, I would try not to go deeper than this (my head seems like to
crack..)
Thank you for your helpful response as always.

Regards.
 

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