Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why unhandled exception in a background thread doesnt crash the app domain?

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();
}
like image 234
Boppity Bop Avatar asked Jun 24 '11 08:06

Boppity Bop


People also ask

What are some of the ways an unhandled exceptions on thread pool threads will terminate the process?

Exceptions in Thread Pool threads Unhandled exceptions on thread pool threads terminate the process with 3 exceptions: A ThreadAbortException is thrown in a thread pool thread, because Abort was called. An AppDomainUnloadedException is thrown in a thread pool thread, because the application domain is being unloaded.

How do you handle an unhandled exception in the thread?

Uncaught exception handler will be used to demonstrate the use of exception with thread. It is a specific interface provided by Java to handle exception in the thread run method. There are two methods to create a thread: Extend the thread Class (java.

What does an unhandled exception do?

An exception is a known type of error. An unhandled exception occurs when the application code does not properly handle exceptions. For example, When you try to open a file on disk, it is a common problem for the file to not exist.

Which event is used for unhandled exceptions?

asax and the Application_Error event handler to execute code when an unhandled exception occurs. Specifically, we used this event handler to notify a developer of an error; we could extend it to also log the error details in a database.


3 Answers

This is happening because the BeginInvoke uses ThreadPool internally and when ThreadPool any unhadled exceptions will be silence fail. However if you use a.EndInvoke then the unhadled exception will be throw at the EndInvoke method.

Note: as João Angelo stated that using ThreadPool methods directly "like ThreadPool.QueueUserWorkItems and UnsafeQueueUserWorkItem" will throw exceptions at 2.0 and above.

like image 178
Jalal Said Avatar answered Oct 15 '22 09:10

Jalal Said


From Exceptions in Managed Threads on MSDN:

In the .NET Framework version 2.0, the common language runtime allows most unhandled exceptions in threads to proceed naturally. In most cases this means that the unhandled exception causes the application to terminate.

This is a significant change from the .NET Framework versions 1.0 and 1.1, which provide a backstop for many unhandled exceptions — for example, unhandled exceptions in thread pool threads. See Change from Previous Versions later in this topic.

As a temporary compatibility measure, administrators can place a compatibility flag in the section of the application configuration file. This causes the common language runtime to revert to the behavior of versions 1.0 and 1.1.

<legacyUnhandledExceptionPolicy enabled="1"/>
like image 37
Jon Grant Avatar answered Oct 15 '22 09:10

Jon Grant


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 call EndInvoke. Also, this should not be confused with Control.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.

static void Throws()
{
    Console.WriteLine("Thread: {0}", Thread.CurrentThread.ManagedThreadId);

    throw new ApplicationException("Test 1");
}

[OneWay]
static void ThrowsButIsIgnored()
{
    Console.WriteLine("Thread: {0}", Thread.CurrentThread.ManagedThreadId);

    throw new ApplicationException("Test 2");
}

static void Main(string[] args)
{
    Console.WriteLine("Main: {0}", Thread.CurrentThread.ManagedThreadId);

    var willIgnoreThrow = new Action(ThrowsButIsIgnored);
    var result1 = willIgnoreThrow.BeginInvoke(null, null);

    Console.ReadLine();
    willIgnoreThrow.EndInvoke(result1);

    Console.WriteLine("============================");

    var willNotIgnoreThrow = new Action(Throws);
    var result2 = willNotIgnoreThrow.BeginInvoke(null, null);

    Console.ReadLine();
    willNotIgnoreThrow.EndInvoke(result2);
}
like image 20
João Angelo Avatar answered Oct 15 '22 08:10

João Angelo