C# Thread Termination and Thread.Abort()
Asked Answered
Q

11

91

In MSDN, the description of the Thread.Abort() method says: "Calling this method usually terminates the thread."

Why not ALWAYS?

In which cases it doesn't terminate the thread?

Are there any other possibility to terminate threads?

Quern answered 12/2, 2010 at 13:14 Comment(0)
F
63

Thread.Abort() injects a ThreadAbortException on the thread. The thread may cancel the request by calling Thread.ResetAbort(). Also, there are certain code parts, such as finally block that will execute before the exception is handled. If for some reason the thread is stuck in such a block the exception will never be raised on the thread.

As the caller has very little control over the state of the thread when calling Abort(), it is generally not advisable to do so. Pass a message to the thread requesting termination instead.

Farther answered 12/2, 2010 at 13:22 Comment(4)
What kind of a message? Do you mean a method invokation?Quern
That depends on how you pass data between your threads. E.g. if your thread is a worker thread with a task queue, you can queue a PleaseTerminate message and let the thread handle it gracefully.Farther
My thread has one big problem that mast be solved, were is no task queue.Quern
As I said, it depends on how your thread code is designed. Perhaps you could signal through a member variable then. It is hard to be more specific without the actual code available.Farther
I
56

In which cases it doesn't terminate the thread?

This question is a duplicate.

What's wrong with using Thread.Abort()

Are there any other posibility to terminate threads?

Yes. Your problem is that you should never start up a thread that you cannot tell politely to stop, and it stops in a timely manner. If you are in a situation where you have to start up a thread that might be (1) hard to stop, (2) buggy, or worst of all (3) hostile to the user, then the right thing to do is to make a new process, start the thread in the new process, and then terminate the process when you want the thread to go down. The only thing that can guarantee safe termination of an uncooperative thread is the operating system taking down its entire process.

See my excessively long answer to this question for more details:

Using lock statement within a loop in C#

The relevant bit is the bit at the end where I discuss what the considerations are regarding how long you should wait for a thread to kill itself before you abort it.

Inventive answered 12/2, 2010 at 16:6 Comment(5)
Eric, how should I politely tell a thread to stop if that thread is waiting on a synchronization object, e.g. EventWaitHandle.WaitOne();?Anglicism
@Corvin: the contract between two threads that describes how one thread is to communicate with another is up to the authors of the code that runs on those threads. If you have requirements that (1) a thread X must wait on an object potentially forever, and (2) that thread Y must be able to cleanly shut down thread X in a finite amount of time then I think you have contradictory requirements; decide which one wins. If the former, then thread Y is going to have to wait. If the latter, then thread X shouldn't be waiting forever, it should wait some small amount of time.Inventive
Thanks for answering. Consider the following architecture: I have an application that has to minimize itself when a certain system-wide event happens. I have a thread in that application that waits on a global named event and does its work when that event is set. On the other side, my application may have to quit before the event happens, having to close that waiting thread. What is the samurai way to code such a thing?Anglicism
@Corvin: You could have a loop that waits (with a short timeout) for the event, then checks if it should stop trying to wait (so it can exit normally). This way, you can signal your thread that it should stop, and you should only have to wait as long as your timeout for it to stop.Whist
@Corvin, if you make that waiting thread a background thread, then you shouldn't have to close it before the application quits.Sounder
S
18

Why not ALWAYS? In which cases it doesn't termenate the thread?

For starters, a thread may catch a ThreadAbortException and cancel its own termination. Or it could perform a computation that takes forever while you're trying to abort it. Because of this, the runtime can't guarantee that the thread will always terminate after you ask it to.

ThreadAbortException has more:

When a call is made to the Abort method to destroy a thread, the common language runtime throws a ThreadAbortException. ThreadAbortException is a special exception that can be caught, but it will automatically be raised again at the end of the catch block. When this exception is raised, the runtime executes all the finally blocks before ending the thread. Since the thread can do an unbounded computation in the finally blocks, or call Thread.ResetAbort() to cancel the abort, there is no guarantee that the thread will ever end.

You don't need to Abort() a thread manually. The CLR will do all of the dirty work for you if you simply let the method in the thread return; that will end the thread normally.

Sideways answered 12/2, 2010 at 13:17 Comment(1)
I do need to Abort() it, because of a message loop started on that thread (Dispatcher.Run();). If I understand it correct, I need to Invoke a method calling return into the thread to finish it?Quern
S
7

FileStream.Read() to a named pipe that is currently not receiving anything (read call blocks while waiting for incoming data) will not respond to Thread.Abort(). It remains inside the Read() call.

Scyros answered 22/9, 2011 at 3:37 Comment(0)
A
6

What if a thread is holding a lock and is aborted / killed ? Resources remain stuck

It works fine when when a thread calls abort itself but not by other thread. Abort, forcefully terminates the affected thread even if it has not completed its task and provides no opportunity for the cleanup of resources

reference MSDN


see: Managed Threading Best Practices

Alcine answered 12/2, 2010 at 13:21 Comment(0)
R
6

I can't seem to abort a thread that is stuck in a loop:

//immortal
Thread th1 = new Thread(() => { while (true) {}});

I can however abort the thread if sleeps during the loop:

//mortal
Thread th2 = new Thread(() => { while (true) { Thread.Sleep(1000); }});
Racine answered 24/11, 2015 at 8:10 Comment(1)
this doesn't appear to be true, I ran a test program:`{var th = new Thread(() => { int i = 0; try { while (true) { i++; } } catch(Exception e) { Console.WriteLine("aborting@ {0}", i); } }); th.Start(); Thread.Sleep(1000); th.Abort(); th.Join(); }Icelandic
T
4

ThreadAborts will not occur inside a finally block or between BeginCriticalRegion and EndCriticalRegion

Tyson answered 12/2, 2010 at 13:29 Comment(0)
T
3

Because you can catch the ThreadAbortException and call Thread.ResetAbort inside the handler.

Twister answered 12/2, 2010 at 14:9 Comment(0)
R
0

OT: For a comprehensive, language-agnostic, questionably useful and darned funny take on concurrency, see Verity Stob!

Ralston answered 12/2, 2010 at 13:29 Comment(0)
D
0

As john feminella stated from MSDN

When this exception is raised, the runtime executes all the finally blocks before ending the thread.

For example this Abort never ends:

var thread = new Thread(action) { IsBackground = true };
thread.Start();
Thread.Sleep(2000);
thread.Abort();

while (!thread.Join(1000))
{
    Console.WriteLine(thread.ThreadState);
}

void action()
{
    try
    {
        while (true) { }
    }
    catch { }
    finally
    {
        while (true) { }
    }
}
Distributee answered 4/10, 2022 at 22:7 Comment(0)
M
-1

I've had cases where the thread has been too busy to hear the Abort() call, which usually results in a ThreadAbortingException being thrown to my code.

Mcloughlin answered 12/2, 2010 at 13:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.