catch exception that is thrown in different thread
Solution 1
In .NET 4 and above, you can use Task<T>
class instead of creating new thread. Then you can get exceptions using .Exceptions
property on your task object.
There are 2 ways to do it:
In a separate method: // You process exception in some task's thread
class Program { static void Main(string[] args) { Task<int> task = new Task<int>(Test); task.ContinueWith(ExceptionHandler, TaskContinuationOptions.OnlyOnFaulted); task.Start(); Console.ReadLine(); } static int Test() { throw new Exception(); } static void ExceptionHandler(Task<int> task) { var exception = task.Exception; Console.WriteLine(exception); } }
In the same method: // You process exception in the caller's thread
class Program { static void Main(string[] args) { Task<int> task = new Task<int>(Test); task.Start(); try { task.Wait(); } catch (AggregateException ex) { Console.WriteLine(ex); } Console.ReadLine(); } static int Test() { throw new Exception(); } }
Note that the exception which you get is AggregateException
. All real exceptions are availible through ex.InnerExceptions
property.
In .NET 3.5 you can use the following code:
// You process exception in the child's thread
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<Exception> handler) { try { test.Invoke(); } catch (Exception ex) { Handler(ex); } } static void Test(int a, int b) { throw new Exception(); } }
Or // You process exception in the caller's thread
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(); } }
Solution 2
You can not catch the exception in Method1. You can, however, catch the exception in Method2 and record it to a variable that the original thread of execution can then read and work with.
Solution 3
I had a particular problem in that I wanted to use items, containing controls, from an integration test suite, so have to create an STA thread. The code I ended up with is as follows, put here in case others have the same issue.
public Boolean? Dance(String name) {
// Already on an STA thread, so just go for it
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA) return DanceSTA(name);
// Local variable to hold the caught exception until the caller can rethrow
Exception lException = null;
Boolean? lResult = null;
// A gate to hold the calling thread until the called thread is done
var lGate = new ManualResetEvent(false);
var lThreadStart = new ThreadStart(() => {
try {
lResult = DanceSTA(name);
} catch (Exception ex) {
lException = ex;
}
lGate.Set();
});
var lThread = new Thread(lThreadStart);
lThread.SetApartmentState(ApartmentState.STA);
lThread.Start();
lGate.WaitOne();
if (lException != null) throw lException;
return lResult;
}
public Boolean? DanceSTA(String name) { ... }
This is a direct paste of the code as-is. For other uses I would recommend supplying an action or function as a parameter and invoking that on the thread instead of hard-coding the called method.
Silverlight Student
Updated on November 06, 2021Comments
-
Silverlight Student over 2 years
One of my method (
Method1
) spawns a new thread. That thread execute a method (Method2
) and during exectution an exception is thrown. I need to get that exception information on the calling method (Method1
)Is there someway I can catch this exception in
Method1
that is thrown inMethod2
? -
Silverlight Student about 13 yearsThanks for your response. So If Method1 is part of Class1 and I have an variable of type Exception in that class. Whenever Method2 throws an exception, it sets that exception variable in Class1 also. Does it sound like a fair design? Are there any best practice ways of handling this scenario?
-
Silverlight Student about 13 yearsSorry but I forgot to mention that I am using .NET 3.5. As per my understanding Task is 4.0 thing?
-
Santanu Maulik about 13 yearsCorrect, you just store the exception and access it later. It's not uncommon for methods run in the future (especially callbacks for when Method2 is complete) to then rethrow that exception as if they themselves had caused it, but this really depends on what you want.
-
oxilumin about 13 years@SilverlightStudent Ok, I just updated my answer to satisfy your requirements.
-
Silverlight Student about 13 years@oxilumin: Thanks and much appreciated. One more followup question. If your Test() method takes a few arguments too, then how will you modify SafeExecute method for those arguments?
-
oxilumin about 13 years@SilverlightStudent In this case I'll pass a lambda instead of
Test
. Like() => Test(myParameter1, myParameter2)
-
Silverlight Student about 13 years@oxilumin: Thanks again, however when I try to do it I am getting compilation errors. Is it possible for you to update example above for that scenario of have to pass in multiple parameters?
-
oxilumin about 13 years@SilverlightStudent: Updated.
-
Peter Kelly over 12 yearsThe exception still goes unhandled before then going on to the catch block in the main thread.
-
Essej over 3 yearsI get compilation errors, "Cannot convert from int to System.Func<int>"