Thread.Abort and Alternatives

This is more out of personal curiosity / interest than the specific problem I'm trying to solve.

Suppose you have a program that performs some operation on user-provided information (such as a search string) that changes as the user enters it. Suppose you want to show the user the most relevant information for what they typed at any given time.

If the threads were indeed canceled, we could just start one thread based on the last modified search string and discard all previous threads that were running.

Now, the generally accepted best practice for this today is to use a delay timer as a user type that waits from 0.5 to 1 second before the operation starts. I hope this is obvious enough that this is not an ideal solution, theoretically (any artificial delay imposes an artificial bottleneck that cannot be overcome, even if it is only 0.5 seconds).

In addition, today's best practice says that any subsequent operations must wait for the completion of the previous test before execution. In a world where we cannot interrupt operations, this makes sense, but, again, theoretically, this is far from ideal. Imagine that the user types one character and stops long enough to start the operation. Suppose it takes 10 seconds to complete this operation. The user is now forced to wait an unacceptable amount of time until the results of his / her request are visible.

A workaround (unideal) for this would be to perform several operations at the same time, assuming it is safe, but it will still lead to a significant decrease in performance.

So, I'm just curious to think about people about this, at least for .NET, and have there been any new developments in this area since the last time I researched them that I should know about (maybe parallel libraries?). I would also be interested to know if any other languages โ€‹โ€‹/ frameworks can handle such fine-grained control of operations better than .NET.

Greetings.

+4
source share
4 answers

With .Net 4 enhancements for concurrent programming , such as TPL and undo , as Mark Byers mentioned. "Never break the thread! If you donโ€™t know exactly what you are doing ... Not even that." the rule, fortunately, was relaxed.

Another tool that allows for a more โ€œcompositeโ€ approach is Reactive Extensions for.NET (Rx) . On the project home page ..

Rx is a library for compiling asynchronous and event-based programs using observable collections.

Recently, they released a practical laboratory ....

Disabling Asynchronous Blues with Reactive Extensions for .NET

... includes a solution that, with an odd coincidence of time, addresses your example ... "Suppose you want to show the user the most relevant information for what they typed at any time" ... and the need to cancel / interrupt / stop task in progress.

Briefly from the Laboratory ...

In our current sample, weve building a simple dictionary that offers expression. When the user enters the search term, the application will be triggered by a call to the web service to get the sentence words back. Since we do not want to block the user interface, it is good to keep in touch with the dictionary asynchronously as well.

After an excellent step-by-step result, the resulting solution ...

var txt = new TextBox(); var lst = new ListBox { Top = txt.Height + 10 }; var frm = new Form { Controls = { txt, lst } }; // Turn the user input into a tamed sequence of strings. var textChanged = from evt in Observable .FromEvent<EventArgs>(txt, "TextChanged") select ((TextBox)evt.Sender).Text; var input = textChanged .Throttle(TimeSpan.FromSeconds(1)) .DistinctUntilChanged(); // Bridge with the web service MatchInDict method. var svc = new DictServiceSoapClient("DictServiceSoap"); var matchInDict = Observable .FromAsyncPattern<string, string, string, DictionaryWord[]> (svc.BeginMatchInDict, svc.EndMatchInDict); Func<string, IObservable<DictionaryWord[]>> matchInWordNetByPrefix = term => matchInDict("wn", term, "prefix"); // The grand composition connecting the user input with the web service. var res = from term in input from word in matchInWordNetByPrefix(term).TakeUntil(input) select word; // Synchronize with the UI thread and populate the ListBox or signal an error. using (res.ObserveOn(lst).Subscribe( words => { lst.Items.Clear(); lst.Items.AddRange((from word in words select word.Word).ToArray()); }, ex => { MessageBox.Show("An error occurred: " + ex.Message, frm.Text, MessageBoxButtons.OK, MessageBoxIcon.Error); })) { Application.Run(frm); } // Proper disposal happens upon exiting the application. 

Enjoy.

+3
source

You should take a look at the parallel task library in .NET 4 and the new undo model . Tasks can be started at the same time, and they can be canceled. This is similar to what you need.

+4
source

Basically, a clean way to interrupt a task is to ask it nicely, and then let it close itself gracefully. It could be a flag, a cancellation token (like parallel extensions), or something like that.

This only works when you are in control of a task โ€” or when it is already programmed for this โ€” but it is useful in a large number of situations.

I do not agree with "waiting for the completion of the previous operation before performing the next". Of course, it depends on the operation, but if you can run two operations in parallel, it can prevent the first of the useless things from completing, and do not mind the first continuing to work until it notices the โ€œstopโ€ flag that you just set in According to the first paragraph of this answer, this is wonderful. It pretty much depends on the situation.

+2
source

Just because you should not abuse Thread.Abort() does not mean that you cannot cancel the operation in the background thread.

 // set to true to cancel volatile bool cancel; // background thread function void foo() { bool done = false; while (!done && !cancel) { ... } } 

The trick is to let the background thread exit cleanly, not unexpectedly.

+1
source

All Articles