How To Stop a Thread in .NET (and Why Thread.Abort is Evil)

0 comments suggest edit

Ian Griffiths (one of my favorite tech bloggers) wrote this fine piece on why Thread.Abort is a representation of all that is evil and threatens the American (and British) way of life.

The problem with Thread.Abort is that it can interrupt the progress of the target thread at any point. It does so by raising an ’asynchronous’ exception, an exception that could emerge at more or less any point in your program. (This has nothing to do with the .NET async pattern by the way - that’s about doing work without hogging the thread that started the work.)

If you’re interested in how Thread.Abort raises an exception in another thread, read Chris Sells’ (another favorite blogger) investigative report here.

I’ve taken this to heart in the design of my Socket server class (which I will release to the public some day) and in any situation where I have a service running that spawns asynchronous operations. Ian’s appoach to cancelling an asynchronous operation is the similar to mine:

The approach I always recommend is dead simple. Have a volatile bool field that is visible both to your worker thread and your UI thread. If the user clicks cancel, set this flag. Meanwhile, on your worker thread, test the flag from time to time. If you see it get set, stop what you’re doing.

One difference is that I chose not to use a volatile bool field. My reasoning was that if my asynchronous operation only reads the value (and never writes it) and just happened to be reading it while my main thread was changing it to false (in response to a user cancellation effort), I’m not so concerned that asynchronous operation might read true even though it’s being set to false. Why not? Well it’ll stay false by the time I check it again and the chance of that small synchronization flaw is very minute and has a low cost even if it does occur.

The question is, am I missing something more important by not using a volatile field in this instance?

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

10 responses

  1. Avatar for Mr. Something
    Mr. Something June 7th, 2005

    Yes, you could be missing something. To use Java as an example, I believe the volatile keyword forces synchronization of the value between threads because each thread has it's own copy of all variables in CPU cache. There could be an issue if you have multiple physical processors and the thread you set the flag false in is on a different processor then the one you're signaling. In that case, (unless I'm off) it's possible there would be a sizeable delay or that the variable change might never make it to the other thread.

  2. Avatar for OwfAdmin
    OwfAdmin July 9th, 2007

    try this useful link:
    http://msdn.microsoft.com/m...

  3. Avatar for saransony
    saransony December 6th, 2007

    .NET allows to call System.Windows.Forms.Control functions only from thread where control was created. To run them from other thread we need to use Control.Invoke (synchronous call) or Control.BeginInvoke (asynchronous call) functions. For task like showing database records we need Invoke. To implement this :Delegate type for calling form function, delegate instance and function called using this delegate Invoke call from worker thread. Next problem is to stop worker thread correctly. Steps to do this:Set event "Stop Thread" Wait for event "Thread is stopped" While waiting for event process messages using Application.DoEvents function. This prevents deadlock because worker thread makes Invoke calls which are processed in main thread. Thread function checks in every iteration whether Stop Thread event is set. If event is set, function makes clean-up operations, sets event "Thread is stopped" and returns.
    try this useful link---
    http://java.sun.com/j2se/1....
    http://www.interact-sw.co.u...

  4. Avatar for chathuranga
    chathuranga December 13th, 2007

    I have an array of threads working on some task... and I wan to end any thread if it's taking time to execute... so what I did was using a Timer and it's event.. called Thread.Abort() on threads taking more time..but as u mention, with the Abort()..s unexpected behavior.. it's hard to expect what I want to succeed. Works most of the time.. can't rely this. Any ideas.
    the way proposed here seems not applicable here for me bcoz the specific thread is working on a time taking method call and no way to repeatedly check a variable to end the thread itself

  5. Avatar for mick
    mick April 9th, 2008

    volatile bools are primative. Use ManualResetEvent instead.

  6. Avatar for Brian
    Brian March 3rd, 2009

    This seems to be out of date as far as finally blocks are concerned ...

    MSDN states ...
    When a thread calls Abort on itself, the effect is similar to throwing an exception; the ThreadAbortException happens immediately, and the result is predictable. However, if one thread calls Abort on another thread, the abort interrupts whatever code is running. There is also a chance that a static constructor could be aborted. In rare cases, this might prevent instances of that class from being created in that application domain. In the .NET Framework versions 1.0 and 1.1, there is a chance the thread could abort while a finally block is running, in which case the finally block is aborted.
    msdn.microsoft.com/en-us/library/ty8d3wta.aspx

  7. Avatar for tqnga
    tqnga December 21st, 2009

    Hello. I'm using multi thread in vb.net. But when I abort thread by this code:
    If Not m_ThreadList(tableKey) Is Nothing Then
    If m_ThreadList(tableKey).IsAlive Then
    CType(m_ThreadList(tableKey), Thread).Abort()
    End If
    End If
    But it throw exception: "property evaluation failed". I'm coming to a deadlock. Pls help me. Thanks a lot

  8. Avatar for Jared Reynolds
    Jared Reynolds January 6th, 2010

    tqnga, use the method also known as a sync lock example here:
    SyncLock readThread
    readThread.Abort()
    readThread = Nothing
    End SyncLock
    read what a synclock does, it stops other threads from running so a thread can be safely aborted, however, you only abort threads outside of the main loop, so say for instance i made a quick module for an example:

    Module ThreadExample
    Dim Stopper As Boolean = True 'stops thread safely then proceeds
    Public I As New System.Threading.Thread(AddressOf RunThread)
    Public Sub BeginThread() 'Begins The Thread
    I.IsBackground = True 'people say it saves ram but idk
    I.Start()
    End Sub
    Public Sub RunThread()
    While Stopper
    'do what ever you want in this thread.
    System.Threading.Thread.Sleep(1000) 'might be useful for you it helps reduce CPU Usage
    End While
    Try
    SyncLock I 'ensures all other threads running stop
    I.Abort()
    End SyncLock
    Catch ex As Threading.ThreadAbortException
    MessageBox.Show(ex.ToString) 'I don't understand why this completely is an error, its more saying that it stopped safely.
    End Try
    End Sub
    Sub StopThread() 'this method stops the thread and makes the loop quit
    Stopper = False 'ensures that the loop will eventually stop
    End Sub
    End Module

  9. Avatar for Dhukkaieswaran
    Dhukkaieswaran June 5th, 2012

    This is very usefull .

  10. Avatar for Activemars
    Activemars January 22nd, 2013

    wery usefull! thanks