我正在制作一个媒体播放器,现在..我已经添加了一个实时搜索功能来搜索歌曲等等(有些东西,比如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#
提前致谢:)
答案 0 :(得分: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属性。
答案 1 :(得分:1)
在ASP.NET中,我们通常使用两种技术
一种完美的方法是将这两种技术结合起来:只搜索搜索条件中是否有3个或更多字符,并使用计时器。