2

I wrote this code snippet:

        static void Main(string[] args)
    {
        Console.WriteLine("Start");

        Thread secondThread = new Thread(ThrowAnException);
        secondThread.Start();

        Console.ReadKey();
    }

    static void ThrowAnException()
    {
        throw new Exception("Second Thread Exception");
    }
}

My understanding is that when the exception happens on the second thread, the exception moves down the thread's stack and if unhandled, the child thread terminates silently. What I am seeing is that the thread is interrupting the main thread and breaking in the ThrowAnException method with an "Exception was Unhandled".

I ran it both with debugging and without and the behavor is the same.

Any ideas what I am doing wrong?

Jamie Dixon
  • 4,204
  • 4
  • 25
  • 47
  • 1
    possible duplicate of [What happens when a .NET thread throws an exception?](http://stackoverflow.com/questions/1668634/what-happens-when-a-net-thread-throws-an-exception) – Euphoric Jun 21 '13 at 15:49
  • How are you "seeing that the thread is interrupting the main thread"? – Timbo Jun 21 '13 at 15:50
  • 1
    `the child thread terminates silently` - where did you come across this? – YK1 Jun 21 '13 at 15:52
  • *...ran it both with debugging and without and the behavor is the same...* With debugging you could see it in visual studio. What you saw without debugging? Just double-clicking the exe will crash the exe with a program-crash dialog. How did *you* get the breakpoint thing without debugging? – inquisitive Jun 21 '13 at 16:03
  • in reverse - 1) without debugging, app crashes with the message - there is no breakpoint. 2) Child thread terminates - isn't that the behavor of the .NET runtime? You are saying that the child thread can terminate the parent thread? 3) I am seeing that with either the VS2012 break (debugging) or the app crashing (non-debug). 4) Not a dup. – Jamie Dixon Jun 21 '13 at 16:08
  • @YK1 That was the behavior of the 1.x runtime. – Brian Rasmussen Jun 21 '13 at 16:26
  • @BrianRasmussen: so i guessed - i've put it in my answer. – YK1 Jun 21 '13 at 16:29
  • @JamieDixon: You should do your best to avoid `Thread` these days. `Task.Run` is superior for 99.9% of real-world use cases. – Stephen Cleary Jun 21 '13 at 17:16

4 Answers4

7

Unhandled exceptions terminate the program since .NET 2.0. Thinking that the main thread gets "interrupted" isn't the right mind-set, the entire program gets aborted and all the threads die. It is the "rude" version of Thread.Abort() and cannot be stopped.

There's one last gasp through the AppDomain.UnhandledException event. It fires to gives you a chance to log the value of e.UnhandledException.ToString() so you'll have a shot at diagnosing the crash. Often overlooked btw but essential to deal with crashes when your program goes out in the wild and users and their machines treat your program in often very surprising ways you didn't envision.

It is actually possible to not make the program crash with an attribute in the .config file that overrides the default CLR policy. But that way lies madness, threads that terminate without finishing their job just cause programs to misbehave in completely undiagnosable ways. Tried in .NET 1.x and rejected as a Bad Idea.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
1

What you see is correct behavior. Unhandled exception in any thread started by user will cause program to crash.

the child thread terminates silently

May be, just maybe what you have described is from the ancient days of .NET 1.x. This is no longer true from .NET 2.0 and later.

All said, there are ways in which one could make threads not make program crash. (This is just for demo, not for practice. Never do it).

  Action a = ThrowAnException;
  a.BeginInvoke(null, null);

This will cause ThrowAnException to be called on ThreadPool thread using APM. You never see the exception till you call EndInvoke. However, APM is no longer recommended way to do asynchrony.

Take look at C# 4.0 Task Parallel Library and C# 5.0 async/await for some .NET/C# awesomeness.

YK1
  • 7,327
  • 1
  • 21
  • 28
0

Your understanding is nearly correct.

Any unhandled exception (except ThreadAbortException) in a thread goes down the call-stack effectively smashing it. then the thread is silently killed. but the disaster doesnt stop there. the exception then goes on to consume the whole running process. but just before the process is killed, AppDomain.UnhandledException event is raised. it gives you an opportunity to log the exception (or put up a big sorry message). The isTerminating property of the UnhanledExceptionEventArgs is always true.

The thing to note is that in dot-net, among threads there is no parent-child relationship. all threads are equal. The only thing below a thread is the AppDomain itself.

Now to explain what you saw, the exception in the second thread (not child thread) did not interrupt or anyway influence the first thread. the second thread is killed. then the whole process is killed. once the process is killed the first thread has no place to hide. it is doomed to death. now if the code is running within visual studio (a debugger is attached) the debugger can catch the exception as soon as it realized that there is no catch block to catch it. that is when you see it breaking in the main thread. the debugger is not just breaking in the main thread, it is suspending ALL the threads, including the one in which the exception has occured. it gives you a chance to modify the code and resume it.

without a debugger, the exception eats its own thread, then it consumes the whole process.

inquisitive
  • 3,549
  • 2
  • 21
  • 47
  • In reality there's a lot less eating and consuming. When the CLR detects an unhandled exception it shuts down. Nothing destructive happens to the threads/process as you suggest. – Brian Rasmussen Jun 21 '13 at 16:25
  • Thanks to all of the answers - If I can mark all 3 correct I will. – Jamie Dixon Jun 21 '13 at 18:39
0

Unhandled exception in can produce different result as following.

  1. If running thread explicitly using Thread class, then any unhandled exception will take application down.
  2. If running thread using Thread Pool( using TPL,ThreadQueueWorker, any other mean) a. If using task non-generic object, then it won't cause application to crash b. if using task, then It will cause application to crash.
Yogesh
  • 3,044
  • 8
  • 33
  • 60