Blog Stats
  • Posts - 99
  • Articles - 5
  • Comments - 42
  • Trackbacks - 108

 

Thread.Abort

I noticed that the last post I made did not aggregate, most likely because I posted it then deleted it then reposted it.

 

Thread.Abort is evil. Especially in the case of dealing with unmanaged resources as chances are they will never be released.

 

A common pattern for dealing with unmanaged resources is to make a managed wrapper. This way if the resource is forgotten about, the object can release the resource when it is garbage collected. Thread.Abort offers some intresting problems with this as you may get aborted between the time you get the resource and the time that you put the wrapper around your unmanaged object to protect it.

Instead of using thread.abort, one should always be using a volatile “stop“ variable. The thread should be checking this variable at intervals to see if its time to stop. If you need to synchronously stop a thread, set the variable then call Join(timeout). If you make it through your timeout and could possibly be dealing with a dead thread, then and only then should you consider using thread.abort.

Here is a basic class illustrating, this is not production code, just typed it into notepad real quick so treat it as such.

 /// <summary>
 /// Base class to inherit long running threads from
 /// </summary>
 public class ThreadedTaskBase
 {
  private Thread m_Thread;
  private volatile bool m_Terminate;
  protected bool Terminate {
   get { return m_Terminate; }
  }

  protected abstract void Run();

  /// <summary>
  /// Starts the thread
  /// </summary>
  public void Start() {
   lock(this) {
    if(m_Thread == null) {
     ThreadStart ts = new ThreadStart(this.Run);
     m_Thread = new Thread(ts);
     m_Thread.Start();
    } else {
     throw new Exception("Thread already created");
    }
   }
  }

  /// <summary>
  /// Stops the thread
  /// </summary>
  public void Stop() {
   lock(this) {
    m_Stop = true;
    m_Thread = null;
   }
  }

  public void StopSynchronous() {
   lock(this) {
    if(m_Thread != null) {
     m_Stop = true;
     bool stopped = m_Thread.Join(10000); //wait 10 seconds
     if(!stopped) { m_Thread.Abort(); }
     m_Thread = null;
    } else {
     throw new Exception("thread already stopped");
    }
   }
  }

  public ThreadedTaskBase()
  {
  }
 }

 

 

In general one would probably not waznt too use a base class for this but instead a wrapper class for a delegate ... such that any delegate can be run in this manner, to change the above code to be a wrapper, add the delegate method to the constructor and you should be off to the races.

Greg

 

 


Feedback

No comments posted yet.


Post a comment





 

Please add 1 and 8 and type the answer here:

 

 

Copyright © Greg Young