C# 自动完成文本框在执行查询时冻结。一定是更好的办法!

C# 自动完成文本框在执行查询时冻结。一定是更好的办法!,c#,wpf,linq,xaml,C#,Wpf,Linq,Xaml,各位!!我尽了最大的努力,却没有找到我想要的帮助 问题 执行查询时,AutoCompleteTextbox冻结并“吃掉”字符 要求 模仿谷歌即时功能 背景 第一件事:C#,WPF,.NET4.0 好了,现在这已经不是问题了,我正在尝试找到实现动态自动完成文本框的最佳方法,该文本框在键入每个字母后查询数据库的结果 激发AutoCompleteTextBox的TextChanged事件时,将执行以下代码: public void Execute(object sender, object p

各位!!我尽了最大的努力,却没有找到我想要的帮助

问题 执行查询时,AutoCompleteTextbox冻结并“吃掉”字符

要求 模仿谷歌即时功能

背景 第一件事:C#,WPF,.NET4.0

好了,现在这已经不是问题了,我正在尝试找到实现动态自动完成文本框的最佳方法,该文本框在键入每个字母后查询数据库的结果

激发AutoCompleteTextBox的TextChanged事件时,将执行以下代码:

    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;
    }
现在,让我们假设
searchunderyings(e.SearchText)
平均需要600-1100ms——在这段时间内,文本框被冻结,它“吃掉”任何按下的键。这是我一直遇到的一个恼人的问题。出于某种原因,
searchunderyings(e.SearchText)
中的LINQ正在GUI线程中运行。我试着把它委托给一个后台线程,但结果还是一样

理想情况下,我希望文本框能够像GoogleInstant那样工作——但我不希望在服务器/查询返回结果之前“杀死”线程

任何人都有经验或可以提供一些指导,使我能够在键入时进行查询,而无需冻结GUI或关闭服务器


谢谢你们

一次又一次地设置绑定源(这就是为什么在后台线程上运行查询并没有什么区别)可能会让您丧命

<>你可以把算法当作一个整体来考虑。根据您的数据,您可以等待用户输入前三个字符,然后对数据库执行一个大型查询。绑定项源一次。之后键入的每个字符仅对已缓存在客户端上的数据执行筛选。这样,您就不会反复访问数据库(这将非常昂贵)

或者考虑从DB中返回三个左右的结果来保持服务序列化时间。

这行:

var result = SearchUnderlyings(e.SearchText);
同步运行,锁定UI线程。解决这一问题的方法是切换到异步模式,在该模式中启动查询,然后在查询完成时执行某些操作


这篇文章很好地演示了它,并展示了一些解决方案-

所以,我们很快就搞定了一些东西。通过异步调用searchunderyings(例如SearchText),我的GUI线程不再被阻塞,文本框也不再“吃”按键。通过添加
lastQueryTag==\u 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;
         });
    });
}

我将测试您的建议(反复设置绑定源代码),看看是否真的是这样,但同时,我非常喜欢您的建议,即查询一次并根据已缓存的数据进行过滤。如果我根据第一个字母进行查询,那么随后键入的每一个字母都会根据缓存的内容进行过滤,会怎么样?无论如何,谢谢你的帖子——让我思考@克里斯-是的,这也是一个很好的方法。首字母的数量实际上取决于您计划收回的记录总数。如果您要查询回的数据多于要绑定的数据,则可以等到有更多的字母时再进行查询。你必须进行实验。谢谢你提供的信息。我曾经尝试过这一点,但我有点懒——我做了:Task.Factory.StartNew(()=>result=searchunderyings(e.SearchText));但是当我不得不实现一些线程安全性时,我变得懒惰了,因为有几个线程试图设置autoCompleteBox.ItemsSource。但是这篇文章很好。非常感谢。我将在提出解决方案后立即编辑/更新我的问题(可能是您的答案和j0rd4n的组合)。当您说该行正在锁定UI线程时,您就搞定了。谢谢。查看我的解决方案,看看我是如何解决的。