Is This Thread.Abort() Normal and Safe

Is this thread.abort() normal and safe?

No, it is not safe. Thread.Abort() is sketchy enough at the best of times, but in this case your control has no (heh) control over what's being done in the delegate callback. You don't know what state the rest of the app will be left in, and may well find yourself in a world of hurt when the time comes to call the delegate again.

Set up a timer. Wait a bit after the text change before calling the delegate. Then wait for it to return before calling it again. If it's that slow, or the user is typing that fast, then they probably don't expect autocomplete anyway.

Regarding your updated (Abort()-free) code:

You're now launching a new thread for (potentially) every keypress. This is not only going to kill performance, it's unnecessary - if the user isn't pausing, they probably aren't looking for the control to complete what they're typing.

I touched on this earlier, but P Daddy said it better:

You'd be better off just implementing
a one-shot timer, with maybe a
half-second timeout, and resetting it
on each keystroke.

Think about it: a fast typist might create a score of threads before the first autocomplete callback has had a chance to finish, even with a fast connection to a fast database. But if you delay making the request until a short period of time after the last keystroke has elapsed, then you have a better chance of hitting that sweet spot where the user has typed all they want to (or all they know!) and is just starting to wait for autocomplete to kick in. Play with the delay - a half-second might be appropriate for impatient touch-typists, but if your users are a bit more relaxed... or your database is a bit more slow... then you may get better results with a 2-3 second delay, or even longer. The most important part of this technique though, is that you reset the timer on every keystroke.

And unless you expect database requests to actually hang, don't bother trying to allow multiple concurrent requests. If a request is currently in-progress, wait for it to complete before making another one.

Is using Thread.Abort() and handling ThreadAbortException in .NET safe practice?

Is using Thread.Abort() and handling ThreadAbortException in .NET safe practice?

TL;DR version: No, isn't.

Generally you're safe when all type invariants (whether explicitly stated or not) are actually true. However many methods will break these invariants while running, only to reach a new state when they are again true at the end. If the thread is idle in a state with invariants held you'll be OK, but in that case better to use something like an event to signal the thread to exit gracefully (ie. you don't need to abort).

An out-of-band exception1 thrown in a thread while in such a invariants-not-true, ie. invalid, state is where the problems start. These problems include, but are certainly not limited to, mutually inconsistent field and property values (data structures in an invalid state), locks not exited, and events representing "changes happened" not fired.

In many cases it is possible to deal with these in clean up code (eg. a finally block), but then consider what happens when the out-of-band exception occurs in that clean up code? This leads to clean up code for the clean up code. But then that code is it self vulnerable so you need clean up code for the clean up code of the clean up code… it never ends!

There are solutions, but they are not easy to design (and tends to impact your whole design), and even harder to test—how to re-create all the cases (think combinatorial explosion). Two possible routes are:

  1. Work on copies of state, update the copies and then atomically swap current for new state. If there is an out-of-band exception then the original state remains (and finalisers can clean up the temporary state).

    This is rather like the function of database transactions (albeit RDBMSs work with locks and transaction log files).

    It is also similar to the approaches to achieving the "strong exception guarantee" developed in the C++ community in response to a paper questioning if exceptions could ever be safe (C++ of course has no GC/finaliser queue to clean up discarded objects). See Herb Sutters "Guru of the Week #8: CHALLENGE EDITION: Exception Safety" for the solution.

    In practice this is hard to achieve unless your state can be encapsulated in a single reference.

  2. Look at "Constrained Execution Regions", but not the limitations on what you can do in these cases. (MSDN Magazine had an introductory article (introduction to the subject, not introductory level), from .NET 2 beta period2).

In practice if you have to do this, using approach #2 to manage the state change under #1 is probably the best approach, but getting it right, and then validating that it is correct (and the correctness is maintained) is hard.

Summary: It's a bit like optimisation: rule 1: don't do it; rule 2 (experts only): don't do it unless you have no other option.


1 A ThreadAbortException is not the only such exception.

2 So details have possibly changed.

Is C#'s using statement abort-safe?

The book's companion web site has more info on aborting threads here.

In short, the first translation is correct (you can tell by looking at the IL).

The answer to your second question is that there may be scenarios where the variable can be legitimately null. For instance, GetFoo() may return null here, in which you wouldn't want a NullReferenceException thrown in the implicit finally block:

using (var x = GetFoo())
{
...
}

To answer your third question, the only way to make Abort safe (if you're calling Framework code) is to tear down the AppDomain afterward. This is actually a practical solution in many cases (it's exactly what LINQPad does whenever you cancel a running query).

Do I have to abort a System.Threading.Thread?

You should avoid Thread.Abort(), use this only when a third-party component blocks a thread. Even then, figure out why it hangs. (Thread.Abort() == Evil) You should always design your threading without Abort().


You should shutdown the Dispatcher if you want to stop thread. Here's an example on how you could implement it.

// a field to store the guiDispatcher.
Dispatcher guiDispatcher;

// wait event.
ManualResetEvent dispatcherInitialized = new ManualResetEvent(false);

Thread viewerThread = new Thread(delegate ()
{
Window window = GetDialog(configuration);
window.Show();
// get a/the dispatcher of this thread.
guiDispatcher = Dispatcher.CurrentDispatcher;

// dispatcher initialized. Set wait event.
dispatcherInitialized.Set();

// run dispatcher.
System.Windows.Threading.Dispatcher.Run();
});

viewerThread.SetApartmentState(ApartmentState.STA);
viewerThread.Start();
dispatcherInitialized.WaitOne();

// ......

// when you want to terminate the thread, just shutdown the dispatcher.
guiDispatcher.BeginInvokeShutdown(DispatcherPriority.Normal);
// you might want to wait until the thread is terminated.
viewerThread.Join();

If the dispatcher stops by it self, the thread will be cleaned-up. If the dispatcher doesn't stop (which prevents the application from terminating), you can add viewerThread.IsBackground = true;

C# - Thread Abort Exception (Thread Abort Exception) rethrowing itself

The point of ThreadAbortException rethrowing itself is to make sure the thread terminates unless the user explicitly calls ResetAbort.

Let me explain:

try
{
// ... Thread abort happens somewhere in here
}
catch (Exception ex)
{
_log.Error(ex);
}

Here you have a typical example of code that ensures no exception propagates from inside the try block. I know that catching Exception is bad practice, but code like this exists nonetheless.

If you call Abort while the thread is inside the try block you still want it to abort. You just can't rely on users writing this sort of code everywhere:

try
{
// ... Thread abort happens somewhere in here
}
catch (ThreadAbortException)
{
throw; // No, you'll NEVER see code like this in real life
}
catch (Exception ex)
{
_log.Error(ex);
}

So, in order to provide a sort of reliable Abort, the exception has to be automatically rethrown, or it may easily get discarded by accident.

ResetAbort is meant for the very rare case when you specifically detect a thread abort, and you exactly know why it happenned, and you want to prevent it.

Needless to say, the use cases for this are extremely rare. Thread aborts are treated by the runtime in a very special way, and you should avoid them whenever possible. Heck, they even aren't reliable as you pointed out, and all this discussion is ignoring CERs which make matters worse.

Question about terminating a thread cleanly in .NET

Unfortunately there may not be a better option. It really depends on your specific scenario. The idea is to stop the thread gracefully at safe points. That is the crux of the reason why Thread.Abort is not good; because it is not guaranteed to occur at safe points. By sprinkling the code with a stopping mechanism you are effectively manually defining the safe points. This is called cooperative cancellation. There are basically 4 broad mechanisms for doing this. You can choose the one that best fits your situation.

Poll a stopping flag

You have already mentioned this method. This a pretty common one. Make periodic checks of the flag at safe points in your algorithm and bail out when it gets signalled. The standard approach is to mark the variable volatile. If that is not possible or inconvenient then you can use a lock. Remember, you cannot mark a local variable as volatile so if a lambda expression captures it through a closure, for example, then you would have to resort to a different method for creating the memory barrier that is required. There is not a whole lot else that needs to be said for this method.

Use the new cancellation mechanisms in the TPL

This is similar to polling a stopping flag except that it uses the new cancellation data structures in the TPL. It is still based on cooperative cancellation patterns. You need to get a CancellationToken and the periodically check IsCancellationRequested. To request cancellation you would call Cancel on the CancellationTokenSource that originally provided the token. There is a lot you can do with the new cancellation mechanisms. You can read more about here.

Use wait handles

This method can be useful if your worker thread requires waiting on an specific interval or for a signal during its normal operation. You can Set a ManualResetEvent, for example, to let the thread know it is time to stop. You can test the event using the WaitOne function which returns a bool indicating whether the event was signalled. The WaitOne takes a parameter that specifies how much time to wait for the call to return if the event was not signaled in that amount of time. You can use this technique in place of Thread.Sleep and get the stopping indication at the same time. It is also useful if there are other WaitHandle instances that the thread may have to wait on. You can call WaitHandle.WaitAny to wait on any event (including the stop event) all in one call. Using an event can be better than calling Thread.Interrupt since you have more control over of the flow of the program (Thread.Interrupt throws an exception so you would have to strategically place the try-catch blocks to perform any necessary cleanup).

Specialized scenarios

There are several one-off scenarios that have very specialized stopping mechanisms. It is definitely outside the scope of this answer to enumerate them all (never mind that it would be nearly impossible). A good example of what I mean here is the Socket class. If the thread is blocked on a call to Send or Receive then calling Close will interrupt the socket on whatever blocking call it was in effectively unblocking it. I am sure there are several other areas in the BCL where similiar techniques can be used to unblock a thread.

Interrupt the thread via Thread.Interrupt

The advantage here is that it is simple and you do not have to focus on sprinkling your code with anything really. The disadvantage is that you have little control over where the safe points are in your algorithm. The reason is because Thread.Interrupt works by injecting an exception inside one of the canned BCL blocking calls. These include Thread.Sleep, WaitHandle.WaitOne, Thread.Join, etc. So you have to be wise about where you place them. However, most the time the algorithm dictates where they go and that is usually fine anyway especially if your algorithm spends most of its time in one of these blocking calls. If you algorithm does not use one of the blocking calls in the BCL then this method will not work for you. The theory here is that the ThreadInterruptException is only generated from .NET waiting call so it is likely at a safe point. At the very least you know that the thread cannot be in unmanaged code or bail out of a critical section leaving a dangling lock in an acquired state. Despite this being less invasive than Thread.Abort I still discourage its use because it is not obvious which calls respond to it and many developers will be unfamiliar with its nuances.

How to use thread.abort()

In case you have to use threads, try this. Otherwise, try cancelAsync like in this link:
https://www.wpf-tutorial.com/misc/cancelling-the-backgroundworker/

     // We will set this true to notify the worker threads return.
private bool shouldAbort;
// when hitting submit set:
shouldAbort = false;
void MethodThatDoesWork()
{
//we should stop if required
if (shouldAbort)
{
state.Stop();
}
//code
}

we must be sure that all threads are terminated when the form is closed.
so we add these controls.

   private void ItemsCopyer_FormClosing(object sender, FormClosingEventArgs e)
{
System.Diagnostics.Process.GetCurrentProcess().Kill();
}

private void btnAbort_Click(object sender, EventArgs e)
{
shouldAbort = true;
btnAbort.Enabled = false;
}


Related Topics



Leave a reply



Submit