From: Tony Johansson on 18 Jun 2010 03:03 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
From: Peter Duniho on 18 Jun 2010 03:16 Tony Johansson wrote: > 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
From: Arne Vajhøj on 20 Jun 2010 22:09 On 18-06-2010 03:03, Tony Johansson wrote: > 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
From: kndg on 20 Jun 2010 23:05 On 6/21/2010 10:09 AM, Arne Vajh�j wrote: > On 18-06-2010 03:03, Tony Johansson wrote: >> 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 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.
From: Peter Duniho on 21 Jun 2010 01:07
kndg wrote: > On 6/21/2010 10:09 AM, Arne Vajh�j wrote: >> On 18-06-2010 03:03, Tony Johansson wrote: >>> 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 > > 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). 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. 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. > 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 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 > 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. The GC can be run concurrently or not, depending on .NET implementation and configuration. > 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). Neither marshaling nor using DirectX actually requires additional threads, or is even done more effectively with additional threads. It's entirely possible that the extra threads seen are simply a result of WPF using the thread pool more heavily, and thus causing more worker threads to be started. If you watch the process long enough, you may find the total thread count goes down, as the thread pool expires threads. Or they could be there for some completely different reason. 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. The main take-away should simply that thread IDs are not guaranteed to be anything other than a unique way to identify a thread (i.e. they aren't necessarily even consecutive, never mind start at 0). Even if it can be explained why the thread IDs are distributed in a certain way to today, that information is purely academic and subject to change in the next revision of .NET. Pete |