There is such a code

using System; using System.IO; namespace ConsoleApplication37 { class Test { public Test() { System.Threading.Thread t1 = new System.Threading.Thread(Foo); System.Threading.Thread t2 = new System.Threading.Thread(Foo); t1.Start(); t2.Start(); } public void Foo() { try { throw new OverflowException(); } catch { Console.WriteLine("Специально созданное исключение"); throw; } } } class Program { static void Main(string[] args) { try { Test p = new Test(); } catch { Console.WriteLine("Какая-то ошибка"); } } } } 

In it, in 2 threads, the same method is triggered, generating an exception. As you can see, after the exception processing in the Foo method, the same exception is passed for processing higher in the hierarchy. But for some reason catch in the Main method does not work at all. Why

    3 answers 3

    Exceptions run through the Thread class are caught in the catch block only in the current thread in which they were generated.
    Accordingly, you cannot catch a re-generated exception in main .

    To catch an exception in another thread, you can use an asynchronous delegate trigger mechanism (instead of using the Thread class). Change the Test class constructor to the following code.

      public Test() { var action = new Action(foo); IAsyncResult result = action.BeginInvoke(null, null); try { action.EndInvoke(result); } catch (Exception e) { Console.WriteLine(e.Message); throw; } } 

    Now in the main method, you can catch your exceptions generated in another thread.

    • Thank. Is there any way to still catch him? Maybe some kind of trick? - Polyakov Sergey 2:43 pm
    • @PolyakovSergey, I will write now. - Alexcei Shmakov
    • @PolyakovSergey, updated the answer. - Alexcei Shmakov
    • Thanks, I will understand - Polyakov Sergey
    • Well, why do BeginInvoke - if EndInvoke is done right away? - Pavel Mayorov

    I would like to share one more way to catch unhandled exceptions, without completing the application. This method is incorrect, and it should be used only in the most extreme cases, when no adequate methods help:

    1) In the configuration file, we return the CLR mode to the behavior of version 1.0-1.1 :

     <runtime> <legacyUnhandledExceptionPolicy enabled="1"/> </runtime> 

    2) To catch unhandled exceptions, subscribe to the UnhandledException event:

     AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { Console.WriteLine((e.ExceptionObject as Exception).Message + " CLR IsTerminating: " + e.IsTerminating); } 

    3) In the Test class constructor, we expect the threads to finish:

     t1.Join(); t2.Join(); 

    All code looks like this:

     namespace ConsoleApplication { class Program { static void Main(string[] args) { AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; var p = new Test(); Console.ReadKey(); } static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { Console.WriteLine((e.ExceptionObject as Exception).Message + " CLR IsTerminating: " + e.IsTerminating); } } class Test { public Test() { var t1 = new Thread(Foo); var t2 = new Thread(Foo); t1.Start(); t2.Start(); t1.Join(); t2.Join(); } public void Foo() { try { throw new OverflowException(); } catch { Console.WriteLine("Специально созданное исключение"); throw; } } } } 

    ps when launched under the Visual Studio debugger, this method will not work, and the studio will show an exception. When you run the exe itself - there will be no exception.

      1. We start working process with exception generation
      2. Catch inside exception
      3. thread.join - waiting for the execution of the workflow
      4. We process caught exceptions in main

      It is also possible in the case of Net 4.0 to use the ConcurrentQueue class, to collect all exceptions inside other threads, and then after executing the threads, you can pull out exceptions.