单独的UI线程上的WPF控件?

Syl*_*ens 5 c# wpf user-interface multithreading wpf-controls

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

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

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

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

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

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

提前致谢 :)

Ric*_*end 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);
    } 


} 
Run Code Online (Sandbox Code Playgroud)

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

Dispatcher.CurrentDispatcher.DelayInvoke("UpdateSearch",
       YourMethodThatStartsBackgroundThread,Timespan.FromSeconds(1));
Run Code Online (Sandbox Code Playgroud)

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