I am completely puzzled. I was so sure that .NET shuts the whole application domain if there is uncaught exception in a thread that I never tested this.
However I just tried the following code and it doesn't fail... Could anyone please explain why?
(Tried in .NET 4 and 3.5)
static void Main(string[] args)
{
Console.WriteLine("Main thread {0}", Thread.CurrentThread.ManagedThreadId);
Action a = new Action(() =>
{
Console.WriteLine("Background thread {0}", Thread.CurrentThread.ManagedThreadId);
throw new ApplicationException("test exception");
});
a.BeginInvoke(null, null);
Console.ReadLine();
}
because exception throw on the given threads stays there unless it is channeled back to the main thread.
That's what backgroundWorker does it for you, if you have exception in the BackgroundWorker's thread, it gets rethrown on the main thread.
this makes async call, which creates another thread to execute this
This is happening because the
BeginInvoke
usesThreadPool
internally and whenThreadPool
any unhadled exceptions will be silence fail. However if you usea.EndInvoke
then the unhadled exception will be throw at theEndInvoke
method.Note: as
João Angelo
stated that usingThreadPool
methods directly "likeThreadPool.QueueUserWorkItems
andUnsafeQueueUserWorkItem
" will throw exceptions at 2.0 and above.From Exceptions in Managed Threads on MSDN:
Normally with asynchronous delegates if the delegated method throws an exception the thread is terminated and the exception will be thrown again in the calling code only when you call
EndInvoke
.This is why when using an asynchronous delegate (
BeginInvoke
) you should always callEndInvoke
. Also, this should not be confused withControl.BeginInvoke
which can be called in a fire and forget manner.Earlier I said normally, because there is a possibility for you to state that the exception should be ignored if the delegate method returns void. To do this you need to mark the method with the
OneWay
attribute.If you run the following example, you will only get an exception when calling
willNotIgnoreThrow.EndInvoke
.