1

Environment:

Let's say I have a main application that:

  • Listen for requests for tasks to do,
  • Perform those tasks (that use some resources (in a physical meaning)) one after another,
  • Must be able to instantly stop a pending task to dispose the resources.

I got two timers:

  • On the timer1 tick, the application is retrieving new requests and store them in a Queue,
  • On the timer2 tick, the application is dequeueing a request to perform the task in a new Thread.

When a user ask to stop all tasks to have the resources free, I plan to simply kill the thread running the current task with Thread.Abort().

Problem:

I would like to be able to save some last configuration when killing the thread from the thread class.

Question:

Is there a way to detect when the thread is killed, like a Thread.OnAborting() event?

Or maybe could I catch the ThreadAbortException raised when calling the Thread.Abort() method? (if so, I don't really know how to do it, could you provide some code example?)

Otiel
  • 18,404
  • 16
  • 78
  • 126

3 Answers3

5

Other than catching the ThreadAbortException no other mechanism exists. Of course, you really do not want to be calling Thread.Abort anyway because the ThreadAbortException gets injected asynchronously and those injections points can be unpredictable. For example, it could be in the middle of a write which might leave the entire AppDomain in a corrupted state. .NET 2.0 added constrained execution regions which makes dealing with thread aborts a lot safer and easier to handle, but it is still incredibly difficult to author a block of code that can guarantee that the AppDomain will not get corrupted. My advice is to punt on the Thread.Abort idea.

Instead what you want to do is send a signal to the thread and allow it terminate gracefully on its own. This can be done with the following mechanisms.

  • Poll a flag
  • Use wait handles
  • Call Thread.Interrupt
  • Use the cancellation mechanisms built into the APIs of long running operations

You can see my answer here for more information.

Community
  • 1
  • 1
Brian Gideon
  • 47,849
  • 13
  • 107
  • 150
  • I chose this answer as The Answer as it provides several ways to handle the end of a `Thread`. I'm gonna go with the "Poll a flag" solution. Nevertheless, solutions from _Emiswelt_ (provides a snippet) and from _Chris Shouts_ are worth taking a look at them. – Otiel Jul 20 '11 at 15:29
1

Leito, it will probably be the best way to design the tasks interruptable by simply settings a flag or issuing a event or signal. Sadly, you've provided to less details for me to provide you with an exact code snippet, but a possible, very basic, solution could be:

class MyTask
{
    bool bShouldDoWork;

    public event EventHandler Aborted;

    public void DoWork()
    {    
         bShouldDoWork = true;          

         while(bShouldDoWork)
         {
              //Do work.
              //But ensure that the loop condition is checked often enough to
              //allow a quick and graceful termination. 
         }

         if(Aborted != null)
         {
              //Fire event
              Aborted(this, EventArgs.Empty);
         }
    }

    //Call this method from another thread, for example
    //when a button is pressed in your UI etc.
    public void Abort()
    {
         bShouldDoWork = false;
    }
}

Please note that this snippet is very basic and might require modification to fit your needs. I hope it helps you to catch the idea of correct multi-threading.

Please do not use Thread.Abort(). It only will give you lots of headache.

Emiswelt
  • 3,909
  • 1
  • 38
  • 56
  • Noted to not use `Thread.Abort` ;). I think I'll go with a boolean flag, it seems to me the solution that is the most adapted to my solution. Your code snippet is a good start, thanks for it. I just have a question on what is the use of the Aborted event? – Otiel Jul 20 '11 at 15:23
  • You kind of asked for it ("Thread.OnAborting() event"), but just remove it, if you don't need it. Hope it works out for you. :) – Emiswelt Jul 20 '11 at 18:53