I was going through Microsoft docs for ThreadPool and they explained that ThreadPool threads are background threads which do not keep the application running if all foreground threads have terminated.
Here is the code snippet:
public static void Main()
{
ThreadPool.QueueUserWorkItem(ThreadProc);
Console.WriteLine("From main foreground thread");
//Thread.Sleep(1000);
Console.WriteLine("Exiting from main");
}
static void ThreadProc(object stateInfo) {
Console.WriteLine("From the thread pool");
}
With Thread.Sleep(1000) uncommented it is sure that the background thread will complete before the main foreground thread exits. But when we comment the sleep part then also I get an output of sort:
From main foreground thread
Exiting from main
From the thread pool
It means that the background thread is still executed even when the main foreground thread has exited. Why so?
The end of the Main method doesn't mean the "foreground" thread has exited. Even if it has, it doesn't mean your process has terminated.
Normally, a process stops when all threads that run in the process (including the ones from the thread-pool, which have queued work) terminate. However, if you exit a process using ExitProcess. The CLR works in a slighly more complicated way (see here), which does quite some clean-up before really existing the application.
As a result, before all working threads get killed, there is pretty some time when work can get done.
Related
I create some threads to do some work using threadpool. Every thread increments finishedThreads variable, so the main thread knows when all the threadpool threads terminate:
// in the main thread
while (finishedThreads < threadsNumber) {
// wait
}
// threads terminated, we can continue
// last line of the threadpool thread
++finishedThreads;
Everything works fine until I create a big amount of threads - over 50. Then the last thread never terminates, so the finishedThreads is still equal threadsNumber-1 and the main thread never continues. I tried to find out why this happens, using debugging, stopping Visual etc. but nothing helped. The thread is not being terminated, although as Visual shows, it does not execute any code. Have you got any ideas on what goes wrong? Thanks in advance.
[EDIT]: That's how I create new threads:
ThreadPool.QueueUserWorkItem(new WaitCallback(myThreadFunc), someData);
I'm familiar with Task and Threads and I already know this.
Here is my code:
static void Main(string[] args)
{
var t = Task.Factory.StartNew(() => {
Thread.Sleep(3000);
Console.WriteLine("Child");
}, CancellationToken.None, TaskCreationOptions.AttachedToParent, TaskScheduler.Default);
Task.WaitAll(t);
Console.WriteLine("Parent");
}
Does Console.WriteLine("Child"); get called regardelss the call of Task.WaitAll(t); In other words: Is there a way to execute ALL started subtasks without waiting them (and not killed as soon as the parent finishes execution)?
A C# program will terminate as soon as there are no foreground threads running. Task.Factory.StartNew uses the thread pool thread to do its work, and thread pool threads are all background threads, not foreground threads, and as such don't prevent the entire program from terminating.
If you want to ensure that the entire program doesn't terminate you need to make sure you have at least one foreground thread running, this means either having the additional work you do in the Task you create do its work in a foreground thread, rather than a background thread (which is appropriate, if you want that work to prevent the application from terminating), or it will mean waiting in your one existing foreground thread for the others to finish.
This question already has answers here:
When does a multithreaded console application exit?
(2 answers)
Closed 6 years ago.
Sorry for asking this rather silly question but I made this program to test whether or not all foreground threads are awaited for their completion before the program terminates.
But in this program, as soon as I hit any key to exit the program, the main thread terminates and then closes the application even while in the middle of executing the other foreground thread.
using System;
using System.Threading;
namespace ForegroundThreads
{
// This is a program to test whether or not the application
// will terminate when there is a pending foreground thread running.
// In describing the difference between foreground and background threads,
// the documentation states that an application will terminate all
// background threads when all foreground threads have finished execution.
// This implies that the application will stall the main thread until
// all foreground threads have completed execution. Let us see if this
// is the case.
// Quote:
// A managed thread is either a background thread or a foreground thread.
// Background threads are identical to foreground threads with one exception:
// a background thread does not keep the managed execution environment running.
// Once all foreground threads have been stopped in a managed process (where the .exe file is a managed assembly),
// the system stops all background threads and shuts down.
// Source: https://msdn.microsoft.com/en-us/library/h339syd0%28v=vs.110%29.aspx
class Program
{
static void Main(string[] args)
{
var t = new Thread(() => { 1000000.Times(() => { Console.WriteLine("Hello"); }); });
t.Start();
Console.WriteLine("Press any key to exit the main thread...");
Console.ReadKey();
}
}
public static class Extensions
{
public static void Times(this int numTimes, Action action)
{
for (int i = 0; i < numTimes; i++, action()) ;
}
}
}
The Behavior I Notice When I Run This Code
On my machine, if I reduce the number of times to a smaller value, say, 1000, it immediately kills all foreground threads when the main thread exits. But if I make the value large, like one million, for instance, the system keeps running that foreground thread I created disregarding all keystrokes until it has finished printing one million times.
Update
GSerg linked to another question that asks the same thing. However, if you read that question closely, the poster of that question is really asking, "What's going on?"
The answer simply quotes the MSDN explaining that all foreground threads are awaited for. My question contends the very thing.
My question is -- why is it that the program waits for the foreground thread to finish sometimes and it doesn't at other times. Hence, that answer in that other question is of no help to me.
My bad, my eyes were not seeing 20-20. The program does indeed wait for the spawned foreground thread to complete execution.
What was happening was that when I reduced the number of iterations by decreasing the value of the integer receiver of the Times method, even when the program actually had finished printing all the Hello's, it appeared to my eyes that the program was still busy printing. That led me to believe that the spawned thread is still running its course, and when I pressed any other key on my keyboard, it immediately terminated the process.
I hava a class:
public class LockTest
{
public void LockThis()
{
lock (this)
{
Console.WriteLine("lock this test");
System.Threading.Thread.Sleep(5000);
}
}
}
in Main:
static void Main(string[] args)
{
LockTest lockTest = new LockTest();
lock (lockTest)
{
//lockTest.LockThis();
System.Threading.Thread thread = new Thread(lockTest.LockThis);
thread.Start();
}
Console.Read();
}
I thought the invoking lockTest.LockThis() will cause a dead lock but it didn't. I don't konw why.
The explanation here is timing.
The code in Main that starts the thread manages to escape the lock before the thread has fully started and gotten to the point where it too will try to take the lock.
Try moving the Console.Read line into the lock block, and you'll see what I mean.
Also note that even if the thread managed to reach the locking code before the Main method has escaped the lock, it will simply wait for that to happen (wait for the main thread to escape the lock), and then continue onwards.
So there is no deadlock here, at all.
A deadlock is when two threads wait for each other, or something similar. You don't have that in this code.
There can be no deadlock in this code.
When the thread LockThis starts, the lock is owned by the main thread, so it starts and then it goes on wait. The main thread continues and exits the lock (the line before the Console.Read). At this time the LockThis thread can continue. No deadlock.
Main Thread LockThis
lock (not started)
start LockThis
try lock, failure, goes in wait
unlock
Console.Read()
awakened because the lock is free
lock
unlock
Another scenario: the main thread starts the LockThis thread. The main thread then continues and exits the lock before the LockThis thread has even begun working, so before it tries to enter the lock. Even in this scenario there is no deadlock.
Main Thread LockThis
lock (not started)
start LockThis
unlock
lock
Console.Read()
unlock
(note that in both cases, the position of the unlock in LockThis is irrelevant. You can move it up or down)
If you look at the wiki you'll see that to have a deadlock one has to have
At least two resources must be non-shareable.
You here have only one resource (the lock (lockTest)).
You are leaving the lock(lockTest) block before the thread locks lockTest.
(the following items has different goals , but im interesting knowing how they "PAUSEd")
questions
Thread.sleep - Does it impact performance on a system ?does it tie up a thread with its wait ?
what about Monitor.Wait ? what is the difference in the way they "wait"? do they tie up a thread with their wait ?
what about RegisteredWaitHandle ? This method accepts a delegate that is executed when a wait
handle is signaled. While it’s waiting, it doesn’t tie up a thread.
so some thread are paused and can be woken by a delegate , while others just wait ? spin ?
can someone please make things clearer ?
edit
http://www.albahari.com/threading/part2.aspx
Both Thread.Sleep and Monitor.Wait put the thread in the WaitSleepJoin state:
WaitSleepJoin: The thread is blocked. This could be the result of calling
Thread::Sleep or Thread::Join, of requesting a lock — for example, by
calling Monitor::Enter or Monitor::Wait — or of waiting on a thread
synchronization object such as ManualResetEvent.
RegisteredWaitHandle is obtained by calling RegisterWaitForSingleObject and passing a WaitHandle. Generally all descendants of this class use blocking mechanisms, so calling Wait will again put the thread in WaitSleepJoin (e.g. AutoResetEvent).
Here's another quote from MSDN:
The RegisterWaitForSingleObject method checks the current state of the
specified object's WaitHandle. If the object's state is unsignaled,
the method registers a wait operation. The wait operation is performed
by a thread from the thread pool. The delegate is executed by a worker
thread when the object's state becomes signaled or the time-out
interval elapses.
So a thread in the pool does wait for the signal.
Regarding ThreadPool.RegisterWaitForSingleObject, this does not tie up a thread per registration (pooled or otherwise). You can test this easily: run the following script in LINQPad which calls that method 20,000 times:
static ManualResetEvent _starter = new ManualResetEvent (false);
void Main()
{
var regs = Enumerable.Range (0, 20000)
.Select (_ => ThreadPool.RegisterWaitForSingleObject (_starter, Go, "Some Data", -1, true))
.ToArray();
Thread.Sleep (5000);
Console.WriteLine ("Signaling worker...");
_starter.Set();
Console.ReadLine();
foreach (var reg in regs) reg.Unregister (_starter);
}
public static void Go (object data, bool timedOut)
{
Console.WriteLine ("Started - " + data);
// Perform task...
}
If that code tied up 20,000 threads for the duration of the 5-second "wait", it couldn't possibly work.
Edit - in response to:
"this is a proof. but is there still a single thread which checks for
signals only ? in the thread pool ?"
This is an implementation detail. Yes, it could be implemented with a single thread that offloads the callbacks to the managed thread pool, although there's no guarantee of this. Wait handles are ultimately managed by operating system, which will most likely trigger the callbacks, too. It might use one thread (or a small number of threads) in its internal implementation. Or with interrupts, it might not block a single thread. It might even vary according to the operating system version. This is an implementation detail that's of no real relevance to us.
While it's true RegisterWaitForSingleObject creates wait threads, not every call creates one.
From MSDN:
New wait threads are created automatically when required
From Raymond Chen's blog:
...instead of costing a whole thread, it costs something closer to (but not exactly) 1/64 of a thread
So using RegisterWaitForSingleObject is generally preferable to creating your own wait threads.
Thread.Sleep and RegisteredWaitHandle work at different levels. Let me try and clear it up:
Processes have multiple threads, which execute simultaneously (depending on the OS scheduler). If a thread calls Thread.Sleep or Monitor.Wait, it doesn't spin - it is put to WaitSleepJoin state, and the CPU is given to other threads.
Now, when you have many simultaneous work items, you use a thread pool - a mechanism which creates several threads, and uses its own understanding of work items to dispatch calls to its threads. In this models, worker threads are called from the thread pool dispatcher to do some work, and then return back to the pool. If a worker thread calls a blocking operation - like Thread.Sleep or Monitor.Wait - the this thread is "tied up", since the thread pool dispatcher can't use it for additional work items.
I'm not familiar with the actual API, but I think RegisteredWaitHandle would tell the thread pool dispatcher to call a worker thread when needed - and your own thread is not "tied up", and can continue its work or return to the thread pool.
ThreadPool.g RegisterWaitForSingleObject does call in its native implementation ultimately
QueueUserAPC. See rotor sources (sscli20\clr\src\vm\win32threadpool.cpp(1981)). Unlike Wait Thread.Sleep your thread will not be put to a halt when you use RegisterWaitForSingleObject.
Instead for this thread a FIFO queue with user mode callbacks is registered which will be called when the thread is in an alertable state. That means you can continue to work and when your thread is blocked the OS will work on the registered callbacks giving your thread do to the opportunity to do something meaningful while it is waiting.
Edit1:
To complete the analysis. On the thread that did call RegisterWaitForSingleObject a callback is called on the thread when it is in an alertable state. Once this happens the the thread that did call RegisterWaitForSingleObject will execute a CLR callback that does register another callback which is processed by a thread pool callback wait thread which is only there to wait for signaled callbacks. This thread pool callback wait thread will then check in regular intervals for signaled callbacks.
This wait thread does finally call QueueUserWorkItem for the signalled callback to be executed on a thread pool thread.