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

流过昼夜 提交于 2021-02-07 03:39:55

问题


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!


回答1:


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




回答2:


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.




回答3:


So, we kind of hacked something quick. By making the calls to SearchUnderlyings(e.SearchText) asynchronous, my GUI thread is no longer blocked and the textbox is no longer "eating" key presses. By adding the lastQueryTag == _lastQuery check, we are trying to ensure some thread-safety, allowing only the most recent query to set the ItemsSource.

Perhaps not the most ideal or elegant solution. I am still open to further critiques and suggestions. Thank you!

private long _lastQuery = DateTime.Now.Ticks;

public void Execute(object sender, object parameter)
{
    var autoCompleteBox = sender as AutoCompleteTextBox;
    var e = parameter as SearchTextEventArgs;

    // removed unecessary code for clarity

    long lastQueryTag = _lastQuery = DateTime.Now.Ticks;
    Task.Factory.StartNew(() =>
    {                        
        var result = SearchUnderlyings(e.SearchText);

         System.Windows.Application.Current.Dispatch(() =>
         {
             if (lastQueryTag == _lastQuery)
                  autoCompleteBox.ItemsSource = result;
         });
    });
}


来源:https://stackoverflow.com/questions/4433874/autocomplete-textbox-freezes-while-executing-query-must-be-a-better-way

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!