Tuesday, August 20, 2013

Safe Way To Abort A Thread in C# - Brief about ThreadAbortException, ThreadInterruptedException and volatile variables

Yeah, one of the favorite questions of any interviewer when it comes to multithreading. 

Are you thinking of Thread.Abort()? Let us see why we shouldn't we consider Abort() on a thread. If below information looks like content of MSDN, bear with me because most of the concepts in this article are from MSDN pages only.

    è When thread abort method is called, ThreadAbortException is raised in the method that is being                 executed. Even if the exception is handled in the thread method, it is re-thrown at the end of catch                   block. Yes, ThreadAbortException is a special kind of exception which is thrown even when it is assumed              to be "handled".

         è Unexecuted finally blocks are executed before the thread is aborted. The thread is not guaranteed                   to abort immediately, or at all. This situation can occur if a thread does an unbounded amount of                      computation in the finally blocks that are called as part of the abort procedure, thereby indefinitely                delaying the abort. To wait until a thread has aborted, you can call the Join method on the thread                   after calling the Abort method, but there is no guarantee the wait will end.

è  If Abort is called on a thread that has been suspended, a ThreadStateException is thrown in the thread that called Abort, and AbortRequested is added to the ThreadStateproperty of the thread being aborted. A ThreadAbortException is not thrown in the suspended thread until Resume is called.

è  If Abort is called on a managed thread while it is executing unmanaged code, a ThreadAbortException is not thrown until the thread returns to managed code.

è  If two calls to Abort come at the same time, it is possible for one call to set the state information and the other call to execute the Abort. However, an application cannot detect this situation.

Now that we saw why terminating a thread by calling Thread.Abort is not a good idea. Let us discuss few approaches of terminating a thread in safer way.

Method 1 – using volatile variable:

Variables that are marked as “volatile” can be accessed across multiple threads in thread-safe manner. We can use this property of volatile variable to control the execution of thread method. Yes, we can terminate the thread based on the value of this volatile variable, the caller can simply set this variable from its code.

Little about volatile keyword:

“The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times.
The volatile modifier is usually used for a field that is accessed by multiple threads without using the lock statement to serialize access.”

A simple but not so accurate example (copy pasted from StackOverflow as-it-is):
volatile bool shutdown = false;

void RunThread()
{
   while (!shutdown)
   {
      ...
   }
}

void StopThread()
{
   shutdown = true;
}

This allows your thread to cleanly finish what it was doing, leaving your app in a known good state.

Method 2 using Thread.Interrupt(), volatile and exception handling for cleaned up termination:

ThreadInterruptedException is an exception which can be handled in the thread method. Thread.Interrupt can be called only on a thread that is in WaitSleepJoin state. Calling Interrupt when a thread is in the WaitSleepJoin state will cause a ThreadInterruptedException to be thrown in the target thread. If the thread is not in the WaitSleepJoin state, the exception is not thrown until the thread enters that state. If the thread never blocks, it could complete without ever being interrupted.

Approach is to handle this exception in the target thread method and exit gracefully. Combining this with a volatile variable like in method 1 will provide much safer way to terminate the thread. It also assures that thread will be “aborted”, sorry let us say terminated even when thread may block in a “sleep” or “wait” state.

Again an example from StackOverflow(as-it-is copied):

try
{
    while (keepGoing)
    {
        /* Do work. */
    }
}
catch (ThreadInterruptedException exception)
{
    /* Clean up. */
}


I have compiled this article from the answers I read on StackOverflow and MSDN articles. If you find useful please thank me by liking this post.

1 comment:

  1. Good Article Manu..
    You have Explained more in details
    Thanks for this.

    ReplyDelete