From: kndg on
On 6/21/2010 1:07 PM, Peter Duniho wrote:
> [...]
> 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.
>
>> 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
>

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.

>> 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.
>

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.
From: Peter Duniho on
kndg wrote:
> 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;
> }

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.

> 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).

There shouldn't be any COM stuff going on in the code you showed. But
then, you also should only be seeing a single thread in Task Manager.
So who knows?

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

Yes. You posted it. :)

> 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.

The Process.Threads property returns "ProcessThread" objects, which
represent _only_ OS threads, not managed threads. The length of the
array returned by the Threads property will be the count of the OS
threads and will have no direct relationship to managed threads at all
(though of course on the normal workstation client implementations of
..NET, a single managed thread is hosted in a single OS thread�but as I
mentioned before, you can't count on this).

> 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.

I agree that if you're running .NET on your desktop computer, with no
special configuration changes, the count of threads returned by
Process.Threads should be the same as the count of managed threads. But
that's practically just coincidence.

Pete
From: kndg on
On 6/22/2010 2:40 PM, Peter Duniho wrote:
> kndg wrote:
>> 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;
>> }
>
> 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.