UnhandledException is not raised when an exception is thrown in another thread

According to Microsoft's documentation, when an unhandled exception occurs in a thread (from a thread pool or thrown using the System.Threading.Thread class), the AppDomain.UnhandledException event should be fired for the AppDomain application by default. Here is the MSDN link that explains this after the second section of the NOTE.

But I can’t reproduce this behavior, as far as I can tell from my test application, it never fires UnhandledException neither by default AppDomain nor in AppDomain, which are used to create the stream. Incorrect documentation or test code?

using System; using System.Runtime.ExceptionServices; using System.Reflection; public class Program { static void Main() { Program.HookAppDomainExceptions(); Test t = CreateTestInsideAppDomain("Nested1"); t.SetupNested1(); Console.ReadLine(); } public static Test CreateTestInsideAppDomain(string appDomainName) { AppDomain nested1 = AppDomain.CreateDomain(appDomainName); string executingName = Assembly.GetExecutingAssembly().FullName; return (Test)nested1.CreateInstanceAndUnwrap(executingName, "Test"); } public static void HookAppDomainExceptions() { AppDomain.CurrentDomain.FirstChanceException += new EventHandler<FirstChanceExceptionEventArgs>(FirstChanceException); AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); } public static void FirstChanceException(object sender, FirstChanceExceptionEventArgs e) { Console.WriteLine("Domain:{0} FirstChanceException Handler", AppDomain.CurrentDomain.FriendlyName); } public static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { Console.WriteLine("Domain:{0} UnhandledException Handler", AppDomain.CurrentDomain.FriendlyName); } } public class Test : MarshalByRefObject { private delegate void Nothing(); public void SetupNested1() { var start = new Nothing(Nested1ThreadStart); start.BeginInvoke(null, null); } static void Nested1ThreadStart() { Program.HookAppDomainExceptions(); Test t = Program.CreateTestInsideAppDomain("Nested2"); t.SetupNested2(); } public void SetupNested2() { Program.HookAppDomainExceptions(); Test t = Program.CreateTestInsideAppDomain("Nested3"); t.ThrowException(); } public void ThrowException() { Program.HookAppDomainExceptions(); throw new ApplicationException("Raise Exception"); } } 
+7
source share
2 answers

In your UnhandledException code UnhandledException not a single AppDomain , because if you call a delegate using BeginInvoke() , any exception that is BeginInvoke() during its execution is EndInvoke() and then EndInvoke() when you call EndInvoke() , which you do not.

If you call EndInvoke() :

 start.EndInvoke(start.BeginInvoke(null, null)); 

or execute the delegate synchronously:

 start(); 

You get similar results: UnhandledException main domain is raised.

If instead, you follow what the documentation says and start a new thread using the Thread class:

 new Thread(Nested1ThreadStart).Start(); 

UnhandledException from Nested1 and the main application domain.

So, to answer your question: the documentation is correct. Your code is incorrect. When you call a delegate asynchronously using BeginInvoke() , you should always call EndInvoke() later.

+10
source

I also had this problem. I used the observation pattern to solve this problem. you can implement an interface in your caller class, which has a method that calls from another thread when an exception occurs.

Here is a link that shows how to implement this pattern. Exploring the observer design pattern.

-one
source

All Articles