captura exceção que é lançada em segmento diferente

Um dos meu método ( Method1 ) gera um novo segmento. Esse thread executa um método ( Method2 ) e durante a execução uma exceção é lançada. Eu preciso obter essa informação de exceção no método de chamada ( Method1 )

Existe alguma maneira eu posso pegar essa exceção no Method1 que é lançada no Method2 ?

   

No .NET 4 e acima, você pode usar Task class Task vez de criar um novo thread. Então você pode obter exceções usando a propriedade .Exceptions no seu object de tarefa. Existem duas maneiras de fazer isso:

  1. Em um método separado: // Você processa a exceção no encadeamento de alguma tarefa

     class Program { static void Main(string[] args) { Task task = new Task(Test); task.ContinueWith(ExceptionHandler, TaskContinuationOptions.OnlyOnFaulted); task.Start(); Console.ReadLine(); } static int Test() { throw new Exception(); } static void ExceptionHandler(Task task) { var exception = task.Exception; Console.WriteLine(exception); } } 
  2. No mesmo método: // Você processa a exceção no encadeamento do chamador

     class Program { static void Main(string[] args) { Task task = new Task(Test); task.Start(); try { task.Wait(); } catch (AggregateException ex) { Console.WriteLine(ex); } Console.ReadLine(); } static int Test() { throw new Exception(); } } 

Observe que a exceção que você recebe é AggregateException . Todas as exceções reais estão disponíveis através da propriedade ex.InnerExceptions .

No .NET 3.5, você pode usar o seguinte código:

  1. // Você processa a exceção no thread do filho

     class Program { static void Main(string[] args) { Exception exception = null; Thread thread = new Thread(() => SafeExecute(() => Test(0, 0), Handler)); thread.Start(); Console.ReadLine(); } private static void Handler(Exception exception) { Console.WriteLine(exception); } private static void SafeExecute(Action test, Action handler) { try { test.Invoke(); } catch (Exception ex) { Handler(ex); } } static void Test(int a, int b) { throw new Exception(); } } 
  2. Ou // Você processa exceção no encadeamento do chamador

     class Program { static void Main(string[] args) { Exception exception = null; Thread thread = new Thread(() => SafeExecute(() => Test(0, 0), out exception)); thread.Start(); thread.Join(); Console.WriteLine(exception); Console.ReadLine(); } private static void SafeExecute(Action test, out Exception exception) { exception = null; try { test.Invoke(); } catch (Exception ex) { exception = ex; } } static void Test(int a, int b) { throw new Exception(); } } 

Você não pode capturar a exceção no método 1. Você pode, no entanto, capturar a exceção no Method2 e registrá-la em uma variável que o thread original de execução possa ler e trabalhar.

O método mais simples para compartilhar dados entre encadeamentos diferentes é o shared data seguinte forma (alguns são pseudocódigo):

 class MyThread { public string SharedData; public void Worker() { ...lengthy action, infinite loop, etc... SharedData = "whatever"; ...lengthy action... return; } } class Program { static void Main() { MyThread m = new MyThread(); Thread WorkerThread = new Thread(m.Worker); WorkerThread.Start(); loop//or eg a Timer thread { f(m.SharedData); } return; } } 

Você pode ler sobre este método nesta introdução agradável sobre multithreading , no entanto, eu preferi ler sobre isso no O'Reilly book C# 3.0 in a nutshell , pelos irmãos Albahari (2007), que também é acessível gratuitamente no Google Books, assim como a versão mais recente do livro, porque ele também cobre agrupamento de threads, threads em primeiro plano versus em segundo plano, etc etc, com código de exemplo simples e agradável. (Isenção de responsabilidade: eu possuo uma cópia desgastada deste livro)

Caso você esteja fazendo uma aplicação WinForms, o uso de dados compartilhados é especialmente útil, porque os controles do WinForm não são seguros para threads. Usando um retorno de chamada para passar dados do thread de trabalho de volta para um controle do WinForm, o thread principal da interface do usuário precisa de um código feio com Invoke() para tornar esse controle seguro para thread. Usando dados compartilhados, em vez disso, e o Single-threaded System.Windows.Forms.Timer , com um curto Interval de digamos 0,2 segundos, você pode facilmente enviar informações do thread de trabalho para o controle sem Invoke .