When does a multithreaded console application exit? - c#

class Program
{
public static void Main(String[] args)
{
var c = new C();
var thread = new Thread(new ThreadStart(c.F));
thread.Start();
Console.WriteLine("Exiting main, but the program won't quit yet...");
}
}
class C
{
public void F()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Waiting {0}", i);
Thread.Sleep(1000);
}
Console.WriteLine("Now the program will quit...");
}
}
What's going on under the hood with a console application that leads to it waiting for the other thread to finish before exiting (pointer to docs fine)?
Note: I know this is a basic question - I just always managed waiting for threads to finish before and never considered there was some infrastructure that did it for me...

A process ends when all foreground threads terminate
From Thread.IsBackground remarks on foreground threads vs background threads:
A thread is either a background thread or a foreground thread. Background threads are identical to foreground threads, except that background threads do not prevent a process from terminating. Once all foreground threads belonging to a process have terminated, the common language runtime ends the process. Any remaining background threads are stopped and do not complete.

Any process which has running thread will not exit till all the threads are exited.
So when the main thread exits it has another thread running and when the tread exits process gets terminated.
To exit the program at any point of time Environment.Exit(0); should work.
This statement will terminate all the treads and process will be terminated this is ungraceful way though

Related

Why Main waits when spinning a new thread, but not so with a task

I wonder why in a console app, if I spin a new thread to run from Main, even though Main will reach the end it will wait, though if I spin up a new task, it will exit and not wait for the task to end.
e.g.
static void Main(string[] args)
{
Thread t = new Thread(new ThreadStart(SomeMethod));
t.Start();
// Main will wait, and app won't close until SomeMethod finishes
}
vs.
static void Main(string[] args)
{
Task.Run(() => SomeMethod());
// Main will close / app shuts down without waiting for SomeMethod to finish
}
When reading the documentation for the Thread.IsBackground property, you'll notice there are two types of threads, background and foreground:
... background threads do not prevent a process from terminating. Once all foreground threads belonging to a process have terminated... any remaining background threads are stopped and do not complete.
The reason why the Thread constructor prevents the Main process from terminating is because by default, it creates foreground threads, while task-based asynchronous operations automatically execute on the ThreadPool, which uses background threads by default, and will allow the process to terminate before they are completed.
You have set SomeMethod to run on a different thread so it's now asynchronous. You aren't waiting for the result so Main will just continue and just exit, killing both threads in the process.
Use:
Task.Run(async () => await SomeMethod());
Assuming SomeMethod is awaitable otherwise you can just await the result externally
Task.Run(() => SomeMethod()).Result;

C# Cannot join main thread

I have very simple code which behavior I cannot understand.
class Program
{
static void Main(string[] args)
{
// Get reference to main thread
Thread mainThread = Thread.CurrentThread;
// Start second thread
new Thread(() =>
{
Console.WriteLine("Working...");
Thread.Sleep(1000);
Console.WriteLine("Work finished. Waiting for main thread to end...");
mainThread.Join(); // Obviously this join cannot pass
Console.WriteLine("This message never prints. Why???");
}).Start();
Thread.Sleep(300);
Console.WriteLine("Main thread ended");
}
}
Output of this never-ending program is:
Working...
Main thread ended
Work finished. Waiting for main thread to end...
Why the threads' code get stuck on the Join() method call? By other print outs can be find out, that already before Join() call, the propertyIsAlive of mainThread is set to false and the ThreadState is Background, Stopped, WaitSleepJoin. Also removing sleeps doesn't make any difference.
What's the reasoning for this behavior? What mystery is under the hood of Join() method and execution of Main method?
Join() works as you expect it to, the issue here is with the assumption that the thread running Main() terminates when Main() returns, which is not always the case.
Your Main() method is called by the .NET framework, and when the method returns, there is additional code executed by the framework before the main thread (and hence the process) exits. Specifically, one of the things the framework does as part of the post-Main code is wait for all foreground threads to exit.
This essentially results in a classic deadlock situation - the main thread is waiting for your worker thread to exit, and your worker thread is waiting for the main thread to exit.
Of course, if you make your worker thread a background thread, (by setting IsBackground = true before starting it) then the post-Main code won't wait for it to exit, eliminating the deadlock. However your Join() will still never return because when the main thread does exit, the process also exits.
For more details on the framework internals that run before and after Main(), you can take a look at the .NET Core codebase on GitHub. The overall method that runs Main() is Assembly::ExecuteMainMethod, and the code that runs after Main() returns is Assembly::RunMainPost.

How To create a foreground task?

I seem to fail to create a foreground task.
my main thread is supppose to call another thread and then exit.
the other thread suppose to run forever
void MainThreadMain()
{
task_main = Task.Factory.StartNew(() => OtherThread()) ;
return;
}
void OtherThread()
{
while(true)
{
TellChuckNorrisJoke();
}
}
how can I ensure task_main will continue running even that Main Thread is dead?
I assumed il do:
task_main.IsBackgorund = false;
but no such option :\
I can make my main thread to wait a signal from my other thread that it passed to Foreground mode. but thats plain silly.
The obvious question is: why don't you run your work on the main thread?
Assuming this is not an option, you should use a Thread not a Task. Then you can set:
Thread.IsBackground = false;
This will prevent your application from terminating while the worker thread is running.

What happens to the main thread in this case

I have the following multithreaded program:
class Program{
static void main(){
(new Thread(DoSomething)).Start();
}
static void DoSomething(){
// Dome something here...
}
}
A couple of questions:
Does the main thread exit after spinning off the child thread?
If it does exit and the child thread is a background thread: Is the main process going to exit or will it wait for the background thread to finish?
"By default, threads you create explicitly are foreground threads. Foreground threads keep the application alive for as long as any one of them is running, whereas background threads do not. Once all foreground threads finish, the application ends, and any background threads still running abruptly terminate.
class PriorityTest
{
static void Main (string[] args)
{
Thread worker = new Thread ( () => Console.ReadLine() );
if (args.Length > 0) worker.IsBackground = true;
worker.Start();
}
}
If this program is called without any arguments, the worker thread will take foreground status and will wait on the ReadLine statement for the user to press Enter. Simultaniously, the main thread exits, but the application keeps running because a foreground thread is still alive.
However, if an argument is passed to Main(), the worker is assigned background status, and the program exits almost immediately as the main thread ends (terminating the ReadLine and the program)."
See Joseph Albahri's (a genius and great guy) page on threading for more information (it is where this was extracted from).
Typically, if you want to wait for the child thread to complete, you'd add a x.Join(); line (where x is the variable of your thread) wherever you want your main thread to stop and wait for the child to complete.
EDIT: So, yes, the main thread will exit unless one of three cases occurs:
a) the spawned thread completes before the rest of the main thread code (if you add any)
b) You have a condition that waits for the thread to complete (such as the Join statement I mentioned, but there are other ways too).
c) The main thread goes into a semi-infinite loop (such as a game/graphics engine).
In your bare-bones example, it will exit for sure (given your question's parameters, a background thread).
EDIT2: Sorry, I seem to have dodged your second question (and actually only considered background threads the whole while). If it's a background thread it will exit as I've explained, if it's foreground then it shouldn't (though I don't have much experience with foreground threads, so I can't say for sure).
So to answer your questions: Yes, the main thread exits. Yes, if the child is specifically a background thread, the process will exit as well.
EDIT3: Final edit, I promise. I just wanted to add some code so that you could prove the answer yourself (which is always nice to be able to do):
static void Main(string[] args)
{
Thread thready = new Thread(DoSomething);
thready.IsBackground = true;
thready.Start();
}
static void DoSomething()
{
while (true)
{
Console.Write("thread's looping \n");
}
}
By toggling the thready.IsBackground = true; to thready.IsBackground = false; you get a program that runs forever (not exiting until the thread does). Leaving it as true will exit very quickly.
Depends on Thread.IsBackground.
The process will not exit before all the foreground threads finish. In the following example...
class Program {
static void Main(string[] args) {
(new Thread(DoSomething)).Start();
}
static void DoSomething() {
Thread.Sleep(5000);
}
}
...the process will exit after 5 seconds.
But in this example...
class Program {
static void Main(string[] args) {
(new Thread(DoSomething) { IsBackground = true }).Start();
}
static void DoSomething() {
Thread.Sleep(5000);
}
}
...the process will exit (almost) immediately. The effect on the child background thread that is still running is similar to forcibly killing the process, so avoid doing that if possible.
main process thread will definitely exit...
edit: i rechecked the docs and found that IsBackground property is false by default...which means the main thread will wait...the earlier response ws with regards to the 2nd question

.NET C# Thread exception handling

I thought I understood this, and am a bit embarrassed to be asking, but, can someone explain to me why the breakpoint in the exception handler of following code is not hit?
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
Thread testThread = new Thread(new ParameterizedThreadStart(TestDownloadThread));
testThread.IsBackground = true;
testThread.Start();
}
static void TestDownloadThread(object parameters)
{
WebClient webClient = new WebClient();
try
{
webClient.DownloadFile("foo", "bar");
}
catch (Exception e)
{
System.Console.WriteLine("Error downloading: " + e.Message);
}
}
You're creating a thread, setting it to be a background thread, and starting it. Your "main" thread is then finishing. Because the new thread is a background thread, it doesn't keep the process alive - so the whole process is finishing before the background thread runs into any problems.
If you write:
testThread.Join();
in your Main method, or don't set the new thread to be a background thread, you should hit the breakpoint.
Your thread is a Background thread (you set it so yourself). This means that when the application completes, the thread will be shut down without being given chance to complete.
Because your main has no further content, it exits immediately and both the application and your thread are terminated.
If you were to add a testThread.Join() call then your thread would complete before the app exited and you'd see the exception caught.
Most likely your background thread isn't started before Main exits - starting a new thread may take a while. Since the additional thread is a background thread it is terminated when Main exits.
For demo purposes, you could have your main method wait - e.g. on user input. This would allow the background thread to start running.
Since the new thread's IsBackground is true, it won't prevent the process from terminating. At the end of Main() the only foreground thread terminates, shutting down the process before the other thread gets that far.
Probably because the main thread is ending before the worker thread. Try adding
Console.ReadKey();
at the end of your Main method.

Categories