5

我正在制作一个媒体播放器,现在.. 我添加了一个实时搜索功能来搜索歌曲等(比如 WMP 实时搜索),即当您输入关键字时,搜索就会发生。

在搜索过程中,访问数据库和加载 IEnumerable 是通过 BackGroundProcess 在另一个线程上完成的。UI 通过调用 UIElement 的调度程序进行更新。

这个过程相当快,但是当您在文本框中输入搜索关键字时,似乎有一点滞后,这是因为 Listbox.ItemSource 更新需要一些时间。即假设您要搜索“Adele”,当您输入“a”时,搜索功能会加载“A”的结果,但是当我们输入整个单词“Adele”时,需要一些时间来显示“d " "e" "l" "e" 并且这些字母之间有轻微的滞后。

在这个搜索过程中,当我停止更新 UI 时,搜索过程看起来非常流畅,这对我来说只是意味着 Listbox 正在锁定线程,所以当 Listbox 完成处理时,播放器的其余 UI 被卡在那里.

所以我相信如果我可以将 Listbox Control 放到另一个 UI 线程中,无论加载 Listbox 所花费的时间如何,我都可以保持播放器的流畅运行。仅供参考:数据虚拟化已经存在,ListBox 的 UI 虚拟化正在运行

如何将 ListBox 控件放到另一个 UI 线程上?WPF, C#

提前致谢 :)

4

2 回答 2

5

如果您在每次按键时都查询数据库 - 这将导致您在快速(甚至正常)打字时出现一些滞后

您最好限制请求,我们使用它来限制调度程序线程。

public static class DispatcherExtensions
{
    private static Dictionary<string, DispatcherTimer> timers =
        new Dictionary<string, DispatcherTimer>();
    private static readonly object syncRoot = new object();

    public static string DelayInvoke(this Dispatcher dispatcher, string namedInvocation,
        Action action, TimeSpan delay,
        DispatcherPriority priority = DispatcherPriority.Normal)
    {
        lock (syncRoot)
        {
            if (String.IsNullOrEmpty(namedInvocation))
            {
                namedInvocation = Guid.NewGuid().ToString();
            }
            else
            {
                RemoveTimer(namedInvocation);
            }
            var timer = new DispatcherTimer(delay, priority, (s, e) =>
                {
                    RemoveTimer(namedInvocation);
                    action();
                }, dispatcher);
            timer.Start();
            timers.Add(namedInvocation, timer);
            return namedInvocation;
        }
    }


    public static void CancelNamedInvocation(this Dispatcher dispatcher, string namedInvocation)
    {
        lock (syncRoot)
        {
            RemoveTimer(namedInvocation);
        }
    }

    private static void RemoveTimer(string namedInvocation)
    {
        if (!timers.ContainsKey(namedInvocation)) return;
        timers[namedInvocation].Stop();
        timers.Remove(namedInvocation);
    } 


} 

假设您没有使用 MVVM,您可以在单击按钮时轻松使用它

Dispatcher.CurrentDispatcher.DelayInvoke("UpdateSearch",
       YourMethodThatStartsBackgroundThread,Timespan.FromSeconds(1));

另外值得注意的是:如果您使用的是 4.5,则可以查看绑定上的Delay属性。

于 2012-11-07T16:02:14.687 回答
1

在 ASP.NET 中,我们通常使用两种技术

  • 最多等待 3 个字符开始搜索。
  • 在用户停止输入后和开始搜索之前等待几毫秒,因为用户输入速度超过几毫秒,您的搜索词将包含多个字符。第二个选项包括在用户开始键入时启动一个计时器,并将该计时器设置为零(不停止它)每个按键按下。当用户停止输入 2000 毫秒(例如)时,您执行搜索

一个完美的方法是将这两种技术结合起来:仅在搜索条件中有 3 个或更多字符时进行搜索,并使用计时器。

于 2012-11-07T16:01:23.860 回答