how many threads are used by one Threading.Timer?

M

mjheitland

Hi,

I like to know how many threads are used by a Threading.Timer object.
When I create a Threading.Timer object calling a short running method
every 5 seconds I expected to have one additional ThreadPool thread.
And that is exactly what MS VIsual Studio shows.

But when I run Processexplorer or Taskmanager I see 2 additional
threads, after a while another 2 additional threads. With the 3 threads
at start time we have totally 7 threads.
Please follow the code below to get the locations of the threads.
Does anyone know

1. Where do the three start threads come from (UI thread, GC?, and ?)

2. Does the timer itself consumes permanently a thread? Not only the
method he invokes? This would explain why we get two additional
threads.
If yes, is it a ThreadPool thread?

3. Why do we see another pair of additional threads?

4. Is it dangerous to use many Threading.Timer objects (even for
shortrunning methods)=

// program to demonstrate thread usage by Threading.Timer
using System;
using System.Threading;
namespace NS_ThreadingTimer
{
class TimerState
{
public int counter = 0; // thread parameter
public volatile Timer tmr; // timer reference needed for disposing
}
class App
{
public static void Main()
{
Console.WriteLine("starting timer, press ENTER ...");
Console.ReadLine();
// VisualStudio shows here one thread:
// NS_ThreadingTimer.App.Main (location)
// ProcessExplorer and TaskManager shows here 3 threads:
// mscoree.dll!_CorExeMain
// mscorwks.dll!DebuggerRCThread::ThreadProcStatic
// mscorwks.dll!Thread::intermediateThreadProc
// start timer immediately, then invoke CheckStatus every 5
seconds.
TimerState s = new TimerState();
TimerCallback timerDelegate = new TimerCallback (CheckStatus);
Timer timer = new Timer (timerDelegate, s, 0, 5000);
s.tmr = timer; // Keep handle to timer, so it can be disposed.
while (s.tmr != null) // Main thread NOP until timer is disposed.
Thread.Sleep(1000);
// VisualStudio shows 2 threads:
// NS_ThreadingTimer.App.Main (location)
// System.IO.__ConsoleStream.ReadFileNative
// ProcessExplorer and TaskManager shows here 7 threads:
// mscoree.dll!_CorExeMain
// mscorwks.dll!DebuggerRCThread::ThreadProcStatic
// mscorwks.dll!Thread::intermediateThreadProc
// mscorwks.dll!ThreadpoolMgr::TimerThreadStart
// mscorwks.dll!ThreadpoolMgr::intermediateThreadProc
// mscorwks.dll!ThreadpoolMgr::intermediateThreadProc
// mscorwks.dll!ThreadpoolMgr::GateThreadStart
Console.WriteLine("Timer example done, press ENTER to continue
....");
Console.ReadLine();
}
static void CheckStatus(Object state)
{
// VisualStudio shows 2 threads:
// NS_ThreadingTimer.App.Main (location)
// NS_ThreadingTimer.App.CheckStatus (location)
// ProcessExplorer and TaskManager shows here 7 threads:
// mscoree.dll!_CorExeMain
// mscorwks.dll!DebuggerRCThread::ThreadProcStatic
// mscorwks.dll!Thread::intermediateThreadProc
// mscorwks.dll!ThreadpoolMgr::TimerThreadStart
// mscorwks.dll!ThreadpoolMgr::intermediateThreadProc
// mscorwks.dll!ThreadpoolMgr::intermediateThreadProc
// mscorwks.dll!ThreadpoolMgr::GateThreadStart
TimerState s =(TimerState) state;
s.counter++;
Console.WriteLine("{0}: {1}.", DateTime.Now.TimeOfDay,
s.counter);
if (s.counter == 10)
{
s.tmr.Dispose();
s.tmr = null;
}
}
}
}


So many questions, but I could not find the answer out of the docs.

Greetings,
Michael Heitland
 
W

Willy Denoyette [MVP]

mjheitland said:
Hi,

I like to know how many threads are used by a Threading.Timer object.
When I create a Threading.Timer object calling a short running method
every 5 seconds I expected to have one additional ThreadPool thread.
And that is exactly what MS VIsual Studio shows.

But when I run Processexplorer or Taskmanager I see 2 additional
threads, after a while another 2 additional threads. With the 3 threads
at start time we have totally 7 threads.
Please follow the code below to get the locations of the threads.
Does anyone know

1. Where do the three start threads come from (UI thread, GC?, and ?)

2. Does the timer itself consumes permanently a thread? Not only the
method he invokes? This would explain why we get two additional
threads.
If yes, is it a ThreadPool thread?

3. Why do we see another pair of additional threads?

4. Is it dangerous to use many Threading.Timer objects (even for
shortrunning methods)=

// program to demonstrate thread usage by Threading.Timer
using System;
using System.Threading;
namespace NS_ThreadingTimer
{
class TimerState
{
public int counter = 0; // thread parameter
public volatile Timer tmr; // timer reference needed for disposing
}
class App
{
public static void Main()
{
Console.WriteLine("starting timer, press ENTER ...");
Console.ReadLine();
// VisualStudio shows here one thread:
// NS_ThreadingTimer.App.Main (location)
// ProcessExplorer and TaskManager shows here 3 threads:
// mscoree.dll!_CorExeMain
// mscorwks.dll!DebuggerRCThread::ThreadProcStatic
// mscorwks.dll!Thread::intermediateThreadProc
// start timer immediately, then invoke CheckStatus every 5
seconds.
TimerState s = new TimerState();
TimerCallback timerDelegate = new TimerCallback (CheckStatus);
Timer timer = new Timer (timerDelegate, s, 0, 5000);
s.tmr = timer; // Keep handle to timer, so it can be disposed.
while (s.tmr != null) // Main thread NOP until timer is disposed.
Thread.Sleep(1000);
// VisualStudio shows 2 threads:
// NS_ThreadingTimer.App.Main (location)
// System.IO.__ConsoleStream.ReadFileNative
// ProcessExplorer and TaskManager shows here 7 threads:
// mscoree.dll!_CorExeMain
// mscorwks.dll!DebuggerRCThread::ThreadProcStatic
// mscorwks.dll!Thread::intermediateThreadProc
// mscorwks.dll!ThreadpoolMgr::TimerThreadStart
// mscorwks.dll!ThreadpoolMgr::intermediateThreadProc
// mscorwks.dll!ThreadpoolMgr::intermediateThreadProc
// mscorwks.dll!ThreadpoolMgr::GateThreadStart
Console.WriteLine("Timer example done, press ENTER to continue
...");
Console.ReadLine();
}
static void CheckStatus(Object state)
{
// VisualStudio shows 2 threads:
// NS_ThreadingTimer.App.Main (location)
// NS_ThreadingTimer.App.CheckStatus (location)
// ProcessExplorer and TaskManager shows here 7 threads:
// mscoree.dll!_CorExeMain
// mscorwks.dll!DebuggerRCThread::ThreadProcStatic
// mscorwks.dll!Thread::intermediateThreadProc
// mscorwks.dll!ThreadpoolMgr::TimerThreadStart
// mscorwks.dll!ThreadpoolMgr::intermediateThreadProc
// mscorwks.dll!ThreadpoolMgr::intermediateThreadProc
// mscorwks.dll!ThreadpoolMgr::GateThreadStart
TimerState s =(TimerState) state;
s.counter++;
Console.WriteLine("{0}: {1}.", DateTime.Now.TimeOfDay,
s.counter);
if (s.counter == 10)
{
s.tmr.Dispose();
s.tmr = null;
}
}
}
}


So many questions, but I could not find the answer out of the docs.

Greetings,
Michael Heitland

What taskman shows you are the OS threads, the two additional threads are
the "Debug helper" and the "Finalizer" thread.
So, a process that loads the CLR always starts with a minimum of 3 threads,
a main thread + the two above mentioned addtional threads. Whenever you
start using Timers or Asynch callbacks, async IO etc..., the CLR will
request the threadpool manager to create some additional threads, the
minimum of initial threads created by the TPM is two plus one watchdog
(gate) thread.

So the picture for your sample looks like :

1. Main thread.
2. Debug helper thread (used by managed debuggers, but always present).
3. Finalizer thread.
4, 5 Threadpool threads
- IOC thread (your timer)
- Worker thread (idle)
6 Threapool manager - Gate


Willy.
 
M

mjheitland

Hi Willy,

thanx for your quick reply.

Now it became clearer to me, but some questions are still left:
1. what is the IOC thread (IO control?)?
2. Is the IOC thread a threadpool thread? May I run into resource
problems, if I use more than 25 Threading.Timer objects (the threadpool
is limited to 25 threads per processor in .NET 1.1)?
3. Why do I see another pair of threads after a while?
4. Is the gate thread also a ThreadPool thread?

Michael
 
W

Willy Denoyette [MVP]

mjheitland said:
Hi Willy,

thanx for your quick reply.

Now it became clearer to me, but some questions are still left:
1. what is the IOC thread (IO control?)?
2. Is the IOC thread a threadpool thread? May I run into resource
problems, if I use more than 25 Threading.Timer objects (the threadpool
is limited to 25 threads per processor in .NET 1.1)?
3. Why do I see another pair of threads after a while?
4. Is the gate thread also a ThreadPool thread?

Michael

1. IOC - (IO) Completion also called a "Completion Port".
2. Yes, there are two distinct Threadpools - A worker threadpool and a CP
threadpool.
- the first has a per process per CPU limit of 25 (default)
- the second has a per process limit of 1000 (default)
You may run into resource problems when you have a lot of timers that have
their handler in parallel for an extended period of time. So you should keep
the time spent in the handler as short as possible, or you should start an
auxiliary thread to handle long running tasks from timer events.

3 If a timer fires the CLR asks the Threadpool to create a worker and a CP
thread.
- the CP thread (only oner per process) manages the timer queue
- the worker runs the timer event-handler
4. No the "gate" (only one per process) is kind of watchdog thread used by
the threadpool manager to monitor the status of the workers and CP's.
Note that all this is internal stuff and may vary with the CLR
implementation and version.

Willy.
 
Top