sriharsha KB
sriharsha KB

Reputation: 127

How to run events sequentially in C# or Similar Frameworks

How to Cancel/Regulate event which is executing in parallel with same event in another thread.

For e.g. In a textbox, every time we enter a character the event fires if text changed event is defined. But after entering first character, the event (Let us call First Event) takes lot of time (as there will be more strings which match a single character), and does some action like changing content of a title label. And after entering a second character the new event which raised to run in parallel takes less time. So now, the second event which fired after entering second character executes fast and returns first and first event executes last and thus, first event's result will be printed ultimately on the label rather than the second one.

Is there a better way to cancel the first event before starting the second event. One thing that comes to my mind is to register threads on a global list variable and kill all threads which are not dead before starting your execution. Will this work?? Any better way to handle this situation.

P.S. I know that search could be initiated after a space or enter to solve this particular issue. But I think you have already noticed my main point. :)

Upvotes: 0

Views: 331

Answers (2)

Aron
Aron

Reputation: 15772

My favourite library for dealing with this exact problem is Rx.Net with TPL. This behaviour can be easily implemented with a combination of a Cancellable Task with an event observer using Observable.FromAsync

Some code!

var textChanged = Observable.FromEventPattern(x => textBox.TextChanged += x, x => textBox.TextChanged -= x)
                        .Select(_ => textBox.Text);
IDisposable eventHandler = textChanged.Throttle(TimeSpan.FromMilliseconds(500))
                              .Select(text => Observable.FromAsync((TaskCancelationToken cancel) => DoSearchTaskAsync(text, cancel)))
                              .Switch()
                              .Subscrible(results =>
                              {
                                  //Update the UI
                              });

Note there is no need to explicitly type any of this...I am only doing it for clarity, but I am more than likely to have mistyped a class name or two...

EDIT

The Search method would be the method body of Task<TReturn> DoSearchTaskAsync(string, TaskCancellationToken).

The magic sauce comes from the Observable.FromAsync and Observable.Switch.

Each time we have a change in the textBox.Text we fire an event. That is filtered by the .Throttle (as you would expect). The clever bit is when we then create a new event source on DoSearchTaskAsync using Observable.FromAsync. At this point we have an IObservable<IObservable<TResult>>, or another way to put it, an eventsource of an eventsource. The switch means we only want the results from the most recently sent eventsource from the outter eventsource, and kill (Dispose) the subscription of previous eventsources.

The act of disposing the previous Observable.FromAsync will cause the TaskCancellationToken to cancel, and prevent its results bubbling up, whilst we subscribe to the new Task.

All very clever stuff, and I only recently came across this AWESOME pattern (I would credit the author if I could).

As for the Observable.FromEventPattern that is pretty unfortunate, as of C#5, there are no first class eventhandlers, so we pass in a lambda for subscription and a lambda for de-subscription.

Upvotes: 1

Robert Levy
Robert Levy

Reputation: 29073

The .NET Task API has the concept of cancellation built in. See this page for an example and links to more information. http://msdn.microsoft.com/en-us/library/dd997396(v=vs.110).aspx

Upvotes: 1

Related Questions