Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autocomplete textbox freezes while executing query. Must be a better way!

Tags:

c#

linq

wpf

xaml

everyone! I searched the best I could and did not find exactly the help I was looking for.

Problem

AutoCompleteTextbox FREEZES and "eats" characters while query is performed

Asking for

Mimic Google Instant functionality

Background

First things first: C#, WPF, .NET 4.0

Ok, now that's out of the way, I'm trying to find the best way to implement a dynamic AutoComplete Textbox, which queries a database for results after each letter typed.

The following code gets executed when the AutoCompleteTextBox's TextChanged event is fired:

    public void Execute(object sender, object parameter)
    {
        //removed some unnecessary code for the sake of being concise

        var autoCompleteBox = sender as AutoCompleteTextBox;
        var e = parameter as SearchTextEventArgs;

        var result = SearchUnderlyings(e.SearchText);

        autoCompleteBox.ItemsSource = result;
    }

Now, let's say that SearchUnderlyings(e.SearchText) takes an average of 600-1100ms - during that time, the textbox is frozen and it "eats" any keys pressed. This is an annoying problem I've been having. For some reason, the LINQ in SearchUnderlyings(e.SearchText) is running in the GUI thread. I tried delegating this to a background thread, but still same result.

Ideally, I would like the textbox to work the way Google Instant does - but I don't want to be "killing" threads before the server/query can return a result.

Anyone have experience or can offer some guidance which will allow me to query as I type without freezing the GUI or killing the server?

Thank you guys!

like image 411
Chris Leyva Avatar asked Dec 13 '10 21:12

Chris Leyva


2 Answers

This line:

var result = SearchUnderlyings(e.SearchText);

Runs synchronously, locking the UI thread. The way to cure this would be to switch to an asynchronous pattern, where you start the query, and then do something when it finishes.

This article demonstrates it pretty nicely, and shows some solutions - http://www.codeproject.com/KB/cs/AsyncMethodInvocation.aspx

like image 52
RichardW1001 Avatar answered Sep 28 '22 07:09

RichardW1001


What is probably killing you is setting the binding source over and over again (which is why running the query on a background thread doesn't make a difference).

You might consider the algorithm as a whole. Depending on your data, you could wait until the user enters the first three characters and then do one large query against the database. Bind the item source once. Each character typed afterwards just performs a filter against your data that is already cached on the client. That way you are not hitting the database over and over (which is going to be terribly expensive).

Or consider just bringing back three or so results from the DB to keep your service serialization time down.

like image 45
Jordan Parmer Avatar answered Sep 28 '22 07:09

Jordan Parmer