Автозаполнение текстового поля зависает при выполнении запроса. Должно быть лучше! - PullRequest
5 голосов
/ 14 декабря 2010

все! Я искал лучшее, что мог, и не нашел именно ту помощь, которую искал.

Проблема

AutoCompleteTextbox останавливается и «ест» символы во время выполнения запроса

Запрашиваемая

Функциональность Mimic Google Instant

Фон

Перво-наперво: C #, WPF, .NET 4.0

Хорошо, теперь это не так, я пытаюсь найти лучший способ реализовать динамическое текстовое поле автозаполнения, которое запрашивает в базе данных результаты после каждой напечатанной буквы.

Следующий код выполняется при возникновении события TextChanged в AutoCompleteTextBox:

    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;
    }

Теперь предположим, что SearchUnderlyings(e.SearchText) занимает в среднем 600-1100 мс - за это время текстовое поле зависает и «съедает» любые нажатые клавиши. Это досадная проблема, с которой я столкнулся. По некоторым причинам LINQ в SearchUnderlyings(e.SearchText) работает в потоке GUI. Я попытался делегировать это в фоновый поток, но все тот же результат.

В идеале я хотел бы, чтобы текстовое поле работало так, как работает Google Instant, но я не хочу «убивать» потоки до того, как сервер / запрос сможет вернуть результат.

Кто-нибудь имеет опыт или может предложить какое-нибудь руководство, которое позволит мне делать запросы при вводе текста, не останавливая графический интерфейс или не убивая сервер?

Спасибо, ребята!

Ответы [ 3 ]

4 голосов
/ 14 декабря 2010

Эта строка:

var result = SearchUnderlyings(e.SearchText);

Работает синхронно, блокируя поток пользовательского интерфейса.Чтобы вылечить это, нужно переключиться на асинхронный шаблон, где вы начинаете запрос, а затем что-то делаете, когда он завершается.

В этой статье это довольно красиво демонстрируется и показаны некоторые решения - http://www.codeproject.com/KB/cs/AsyncMethodInvocation.aspx

2 голосов
/ 14 декабря 2010

Что, вероятно, убивает вас - это снова и снова устанавливать источник привязки (поэтому выполнение запроса в фоновом потоке не имеет значения).

Вы можете рассмотреть алгоритм в целом. В зависимости от ваших данных, вы можете подождать, пока пользователь введет первые три символа, а затем сделать один большой запрос к базе данных. Свяжите источник предмета один раз. Каждый введенный впоследствии символ просто выполняет фильтрацию ваших данных, которые уже кэшированы на клиенте. Таким образом, вы не попадаете в базу данных снова и снова (что будет очень дорого).

Или попробуйте вернуть три или около того результатов из БД, чтобы сократить время сериализации службы.

1 голос
/ 15 декабря 2010

Итак, мы что-то быстро взломали. Делая вызовы SearchUnderlyings (e.SearchText) асинхронными, мой поток GUI больше не блокируется, и текстовое поле больше не «жрет» нажатия клавиш. Добавляя проверку lastQueryTag == _lastQuery, мы пытаемся обеспечить некоторую потокобезопасность, позволяя устанавливать только ItemsSource только для самого последнего запроса.

Возможно, не самое идеальное или элегантное решение. Я все еще открыт для дальнейшей критики и предложений. Спасибо!

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;
         });
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...