So I know that you shouldn't use
Thread.Abort()
But I've never been given a good explanation. Is there a performance penalty or some hidden gotcha?
I know you can't ignore/swallow the ThreadAbortException
(which makes sense)
So I know that you shouldn't use
Thread.Abort()
But I've never been given a good explanation. Is there a performance penalty or some hidden gotcha?
I know you can't ignore/swallow the ThreadAbortException
(which makes sense)
In addition to all of the other good answers here, let me add that there is no guarantee whatsoever that a call to Thread.Abort will actually abort the thread in question, ever. It is possible (though not particularly easy) to "harden" a thread against being aborted. If, for example, you are aborting a thread because you believe it to be running hostile code then the hostile code could be resisting its own destruction.
If you have a long-running operation involving code that you do not own that must be taken down cleanly, the correct way to do this is to put that code in its own process, not its own thread. (And preferably in a highly security-restricted appdomain in that process.) You can then cleanly kill the process.
In short, Thread.Abort is at best indicative of bad design, possibly unreliable, and extremely dangerous. It should be avoided at all costs; the only time you should ever even consider aborting a thread is in some sort of "emergency shutdown" code where you are attempting to tear down an appdomain as cleanly as possible.
AppDomain.Unload
to tear down an app domain? AppDomain.Unload
will call Thread.Abort
on all threads running in the domain for you. –
Birr Thread.Abort
so that you don't get a CannotUnloadAppDomainException
if the aborting takes some time. By using Thread.Abort
, you can wait for the thread to really abort, and only then call AppDomain.Unload
. –
Birr Because if you know that the thread is in some safe state in which it can be aborted, surely you can arrange better communication and have the thread exit cleanly.
The thread could have taken a lock and be in the middle of changing some shared state, and the Thread.Abort will undo the lock and leave the shared state corrupted.
Abort
can happen anywhere (in managed code) - even the lock
statement itself actually isn't abort-safe. So you could not only be left with a corrupted state, you could in fact have a lock
that's impossible to release - it will be released when the thread dies, of course, but that doesn't actually have to happen, ever (until the process dies). –
Federicofedirko finally
clause that correctly handles all that? It can be made much easier by avoiding shared state, of course, and only updating the shared state when in a safe, constrained region... but then you're well on your way to not needing the explicit shared state already. –
Federicofedirko It's easier to hurt yourself. As others have stated, it raises an exception in the code, which can occur at any point. This might be fine if you expect this and have coded in a way that elegantly handles this exception at any point, but some people don't:
Monitor.Enter(obj);
// some code - if exception is raised here, then the lock isn't released
Monitor.Exit(obj)
IDisposable someCriticalResource = GetResource();
// some code - if exception is raised here, then the object isn't disposed
someCriticalResource.Dispose();
Additionally, if you're working with many people on a team, unless you have good code reviews, you cannot guarantee the quality of the code you'll be working with. Hence it is a good idea to preach the gospel of "no Thread.Abort()" than it is to get people to remember to write code that is robust against exceptions occurring anywhere within that code.
using
is not abort-safe either - there's a (tiny) window of opportunity between creating the instance and the start of the try-finally
block. It's a great recipe for subtle bugs you will not ever be able to reproduce and that can easily corrupt your data, hang or kill your application etc. –
Federicofedirko In short. Any IDisposable object may not be disposed. Any locked object may not be unlocked. Anything that must be 100% performed will never be done.
Abort
will execute finally
blocks and hence it will dispose IDisposable
also it releases any locks due to same reason. –
Multicolor finally
will run. Doesn't matter you use using
statement or not. –
Multicolor using(acquire) body;
is { acquire; try { body } finally { dispose }}
. What if the abort happens after the acquire step but before the try
is entered? Or, worse: what if the acquire step is new Foo()
where the constructor opens a file handle and assigns it to a field; what if the abort happens after the open but before the assignment? This answer is absolutely correct; an abort can cause a disposable resource to go undisposed. –
Laryngeal When you call Thread.Abort() on another thread, a ThreadAbortException is injected in the flow of that thread. If you're lucky, the code will handle this well and abort in a well-defined state. The problem is that you have no way to figure out if you will be lucky in every case, so if you prefer safe over sorry, calling Thread.Abort on other threads is not a good idea.
Thread.Abort stops your thread in an uncontrolled fashion. thread.Abort will throw an exception, which will cause that your thread stops immediately.
What is wrong with that: in most cases, you want to gracefully stop the operation that you're performing. For instance, if you are executing an ACID operation, you might want to complete the current operation before ending the thread, so that your system remains in a stable state.
Thread.Abort rises an exception in the target thread. Target thread in the meantime can be performing some critical operations and rising an exception can break your application state.
© 2022 - 2024 — McMap. All rights reserved.