Thursday, July 20, 2006 4:12 PM
If you use a try/catch block to call a method asynchronously using BeginInvoke, then BeginInvoke returns very quickly and if you do not have much work to do, you will exit the try/catch block quickly.
If, in the mean time, the called method on the worker thread throws an exception, it will not be caught by the calling method since it has already left the try/catch block and could even have returned altogether.
What is the best way to handle exceptions thrown by asynchronous methods? I see at least a couple of alternatives :
1) Be sure to catch all exceptions in the async. method and return either the exception object, or the exception message as a return value. If no exception is thrown, return null. Then harvest this result in the callback when you call EndInvoke. If there is no exception (i.e. null) then proceed normally. If there is a return value, then either deal with it or throw it back up the call stack, depending on if you are in the top UI layer or not.
2) Try catching the exception in the callback method. I tried this - it sort of works, but the VS 2005 debugger still stops at the original exception and claims that it is unhandled.
I am somewhat confused by all this and would appreciate some guidance as to how best to deal with this. This is a Windows Forms .NET application.
Thursday, July 20, 2006 10:26 PMModeratorOption #1 is of course the only realistic one. You already found that out. When the async method fails, there is very little that you can do in the main thread, other than telling the user, "sorry, I couldn't do it and this is why, please call me". So, keep it simple: have a String variable in that reports the outcome of the async call. Set it to "" when you start the job, set it to Exception.Message when it fails. After EndInvoke, or IAsyncResult.IsCompleted returns True, look at that variable and humbly report the outcome...
Friday, July 21, 2006 11:16 AM
Actually, since I posted this I have found out that the CLR will catch the unhandled exception thrown in the Asynchronous method and rethrow it when the EndInvoke method is called. This is new behaviour in .NET Framework 2.0. In .NET 1.1, the CLR "ate up" asynchronous exeptions and did not report them in EndInvoke.
Also, if you run code like this in VS 2005, the debugger will report an unhandled exception in USER CODE, not that it is unhandled period. The debugger will stop at the thrown exception, but the code can continue and then be caught in a try/catch block around EndInvoke in the callback method. If you run the code outside the debugger, then it works as expected and reports the exception in the callback.
So VS 2005 and .NET 2.0 enables exceptions previously caught and unreported in VS 2003 to be found and identified.
See this previous posting :