If I need to cancel some operation on a thread, when should I use Thread.Abort vs Thread.Interrupt. I read the documentation on it but not sure which scneario should i use a particular call between two.
If there is any third way of doing it, please let me knwo about it too with pro and cons.
I would avoid using Thread.Abort at all costs. Its behavior is much safer and predictable since .NET 2.0, but there are still some pretty serious pitfalls with it. Most of the aborts inside managed code can be made safe, but not all of them. For example, I believe there are some subtle problems if an abort request is triggered during the processing of a static constructor. Nevermind, the fact that the out-of-band exception can occur at anytime giving you little control over defining where the safe points for shutdown are located.
There are several acceptable ways to terminate a thread gracefully.
Use Thread.Interrupt
Poll a stopping flag
Use WaitHandle events
Specialized API calls
I discuss these methods in my answer here.
Most suggestions are already done, but here's an example how i would do it:
ManualResetEvent _requestTermination = new ManualResetEvent(false);
Thread _thread;
public void Init()
{
_thread = new Thread(() =>
{
while (!_requestTermination.WaitOne(0))
{
// do something usefull
}
}));
_thread.Start();
}
public void Dispose()
{
_requestTermination.Set();
// you could enter a maximum wait time in the Join(...)
_thread.Join();
}
This way the dispose will wait until the thread has exited.
If you need a delay within the thread, you shouldn't add Thread.Sleep.
Use the WaitOne(delayTime). This way you will never have to wait to terminate it.
I wouldn't use Thread.Abort ever. It causes an exception at an almost arbitrary time.
Be careful with Thread.Interrupt. If you don't build in some waiting or sleeping time the thread won't be interrupted.
Be careful with Thread.Abort. If you catch the ThreadAbortException your thread will terminate right after catch + finally.
(I like to use those methods to send a signal to my thread so that it knows it's terminating time, then clean up and exit.)
Related
So, a little background. I have a program that creates a child process that runs long term and does some processing that we don't really care about for this question. It exists, and it needs to keep existing. So after starting that child process I start a thread that watches that child process and blocks waiting for it to end by Process.WaitForExit() and if it ends, it will restart the child process and then wait again. Now the problem is, how do I gracefully shut all of this down? If I kill the child process first, the thread waiting on it will spin it up again, so I know that the watcher thread needs to be killed first. I have been doing this by Thread.Abort() and then just catching the ThreadAbortException and returning ending the watcher thread and then I kill my child process. But I have been told that Thread.Abort() should be avoided at all costs and is possibly no longer supported in .Net core? So my question is why is Thread.Abort() so dangerous if I am catching the ThreadAbortException? and what is the best practice for immediately killing that thread so it doesn't have a chance to spin up the child thread again during shut down?
What you are looking for is way to communicate across threads. There are multiple ways to do this but they all have specific conditions applicable.
For example mutex and semaphore are available across processes. events or wait handles are specific to a given process, etc. Once you know the details of these you can use them to send signal from one thread to another.
A simple setup for your requirement can be -
Create a resetevent before spawning any of your threads.
Let the child thread begin. In your parent wait on the reset event that you have created.
Let the child thread reset the event.
In your parent thread the wait state is completed, you can take further actions, such as kicking of the thread again and waiting on it or simply cleaning up and walking out of execution.
Thread.Abort is an unclean way of finishing your processing. If you read the msdn article here - https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread.abort?view=net-6.0 the remark clearly tells you that you cant be sure what current state your thread execution was in. Your thread may not get opportunity to follow up with important clean up tasks, such as releasing resources that it does not require no more.
This can also lead to deadlock if you have more complicated constructs in place, such as thread being aborted doing so from protected region of code, such as a catch block or a finally block. If the thread that calls Abort holds a lock that the aborted thread is waiting on, a deadlock can acquire.
Key to remember in multithreading is that it is your responsibility to let the logic have a clean way of reaching to completion and finish thread's execution.
Please note that steps suggested above is one way of doing it. Depending on your requirements it can be restructured/imporved further. For example, if you are spawning another process, you will require kernel level objects such as mutex or semaphore. Objects like event or flag cant work across the process.
Read here - https://learn.microsoft.com/en-us/dotnet/standard/threading/overview-of-synchronization-primitives for more information.
As mentioned by others, Thread.Abort has major issues, and should be avoided if at all possible. It can raise the exception at any point in the code, in a possibly completely unexpected location, and possibly leave data in a highly corrupted state.
In this instance, it's entirely unnecessary.
You should change the waiting thread to use async instead. For example, you can do something like this.
static async Task RunProcessWithRestart()
{
using cancel = new CancellationTokenSource();
try
{
while (true)
{
using (var process = CreateMyProcessAndStart())
{
await process.WaitForExitAsync(cancel.Token);
}
}
}
catch(OperationCanceledException)
{
}
}
static CancellationTokenSource cancel;
public static void StartWaitForProcess()
{
Task.Run(RunProcessWithRestart);
}
public static void ShutdownWaitForProcess()
{
cancel.Cancel();
}
An alternative, which doesn't require calling Cancel() from a separate shutdown function, is to subscribe to the AppDomain.ProcessExit event.
static async Task RunProcessWithRestart()
{
using var cancel = new CancellationTokenSource();
AppDomain.ProcessExit += (s, e) => cancel.Cancel();
try
{
while (true)
{
using (var process = CreateMyProcessAndStart())
{
await process.WaitForExitAsync(cancel.Token);
}
}
}
catch(OperationCanceledException)
{
}
}
public static void StartWaitForProcess()
{
Task.Run(RunProcessWithRestart);
}
I have 2 threads in my program. 1 is handling a GUI and the other is doing some word automation. Lets call them GUIThread and WorkerThread.
The WorkerThread is looping through methods using recursion.
The WorkerThread is only alive while doing the word automation and the user must be able to stop the word automation. Therefore I have implemented a "Stop" button on the GUI which simply kills/terminates the WorkerThread. However if I kill the WorkerThread while it's in the middle of a method it sometimes causes a problem in my word document (this is a longer story) and that's why I want to check if the WorkerThread has finished/returned from a method before I kill it.
This is what my code does when I hit the "Stop" button:
//Stops the worker thread = stops word automation in process
workerThread.Abort();
//This blocks the thread until the workerThread has aborted
while (workerThread.IsAlive) ;
My own suggestion/workaround for the problem was to have a global variable I could set each time the WorkerThread entered and left a method but this doesn't seem right to me. I mean I think there must be an easier way to deal with it.
However if I kill the WorkerThread while it's in the middle of a method it sometimes causes a problem in my word document
This is why you should never kill a thread. You can't say what the thread was doing, whether it is safe to kill? etc etc.
Abort isn't doing what you expect it to do. Look at the documentation, it is subtle Calling this method usually terminates the thread. Note the word usually and not always.
Yes, Abort will not kill the thread always. For example if the thread was running unmanaged code, CLR will not abort the thread, instead it will wait for the thread to return to managed code.
Sameway Abort will not do its job when thread is in Constrained Execution Region, finally blocks etc.
The CLR delays thread aborts for code that is executing in a CER.
For example: Try to run the following code and see what happens.
private void IWillNeverReturn()
{
Thread thread = new Thread(() =>
{
try
{
}
finally
{
while (true)
{ }
}
});
thread.Start();
Thread.Sleep(1000);
thread.Abort();
}
Let the thread decide when it should complete, Tell the thread that it should stop as soon as it can. You tell it using CancellationToken.
If you google for Thread.Abort Evil, you'll find lot of useful resources, Here is one.
According to documentation, WaitHandle in .NET should be explicitly/implicitly disposed. However, I'm having trouble achieving this for the following basic synchronization task:
a time consuming task is being executed on a thread.
the main thread waits for the task to complete for a predefined time-period. The main thread must proceed if a. the task is completed or b. the timeout occurred.
Here my attempt at using an AutoResetEvent object:
using(var waitHandle = new AutoResetEvent(false)){
var worker = new Thread(() =>
{
try
{
TimeConsumingTask();
waitHandle.Set(); //throws System.ObjectDisposedException: Safe handle has been closed
}
catch (Exception e)
{...}
}) {IsBackground = true};
worker.Start(); //start worker
const int waitTimeInMs = 5000;
var signaled = waitHandle.WaitOne(waitTimeInMs);//block main thread here.
if (!signaled)
{ //if timed out
worker.Interrupt();
}
}
There is an obvious race condition where the main thread wait times out and disposes the wait handle object which causes ObjectDisposedException exception. Is there any other way that I set this up so that the handle is properly disposed and without causing the exception?
Sure, there's no decent way to do this. Do note up front that you painted yourself into that corner by essentially leaving a thread running wild, nothing particularly nice about that.
But you are focusing on the much smaller problem. The Thread class itself is already a resource hog, consuming a megabyte of VM and five synchronization objects. But it has no Dispose() method. This was courageous design, there's just no decent way to call the method.
Disposing is optional, nothing that dramatic happens when you don't call it. The class has got your back, it has a finalizer that ensures that the native operating system resource will be released. Which will run, eventually, just not as quickly as you'd like.
Compare this to a class with a less courageous design, the Task class has a Dispose() method. Which, like Thread, is almost as hard to call. The guidance from the .NET gurus is to just not bother.
Same here.
The waithandle is disposing because your using scope invokes a new thread an returns immediately, causing the waithandle to dispose.
What you should do is explicitly call dispose after you finish your work instead of your using statement:
waitHandle.WaitOne(waitTimeInMs);
if (!signaled)
{ //if timed out
worker.Interrupt();
}
waitHandle.Dispose();
Is there a standard way to close out an application "cleanly" while some WaitHandle objects may be in the state of a current blocking call to WaitOne?
For example, there may be a background thread that is spinning along in a method like this:
while (_request.WaitOne())
{
try
{
_workItem.Invoke();
}
finally
{
OnWorkCompleted();
}
}
I see no obvious way to dispose of this thread without calling Thread.Abort (which from what I understand is discouraged). Calling Close on the _request object (an AutoResetEvent), however, will throw an exception.
Currently, the thread that is running this loop has its IsBackground property set to true, and so the application appears to close properly. However, since WaitHandle implements IDisposable, I'm unsure if this is considered kosher or if that object really ought to be disposed before the app exits.
Is this a bad design? If not, how is this scenario typically dealt with?
Define an additional WaitHandle called _terminate that will signal a request to terminate the loop and then use WaitHandle.WaitAny instead of WaitHandle.WaitOne.
var handles = { _request, _terminate };
while (WaitHandle.WaitAny(handles) == 0)
{
try
{
_workItem.Invoke();
}
finally
{
OnCompleteWork();
}
}
When a thread is blocking (regardless of what it's blocking on) you can call Thread.Interrupt() This will cause the exception ThreadInterruptedException (I believe, it might be a little different) You can handle this exception on the thread itself and do any neccesary clean up.
It's worth noting, that the thread will only throw the ThreadInterruptedException when it is blocking, if it's not blocking it won't be thrown until it next tries to block.
This is the "safe" way of ending threads from what I've read on the subject.
also worth noting: If the object implements both IDisposable and a finializer (which it will if it uses unmanaged resources) the GC will call the finalizer which normally calls dispose. Normally this is non-deterministic. However you can pretty much guarantee they will get called on application exit. Only under very special circumstances they wouldn't. (A .net environment termininating exception such as StackOverflowException is thrown)
Set the IsBackground property to true... it should automatically close the thread when your app ends.
Alternately, you can interrupt the thread by calling Thread.Interrupt and handle the ThreadInterruptedException. Another idea is to call _request.Set() and make the while loop check a volatile flag to determine if the application is closing or if it should continue:
private volatile bool _running = true;
while(_request.WaitOne() && _running)
{
//...
}
// somewhere else in the app
_running = false;
_request.Set();
I think the operating system will clean up after your process has finished. Because your thread is marked as IsBackground the CLR will end the process and all the threads within, so this is not a problem.
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?
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.
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.
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.
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.
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
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); }});
ThreadAborts will not occur inside a finally block or between BeginCriticalRegion and EndCriticalRegion
Because you can catch the ThreadAbortException and call Thread.ResetAbort inside the handler.
OT: For a comprehensive, language-agnostic, questionably useful and darned funny take on concurrency, see Verity Stob!
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) { }
}
}
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.