我有一个TreeView
,包含1000个项目。当我选择一个项目时,TreeView
会触发一个事件,以便我可以在GUI中更新某些内容。事件处理程序是非递归的,没有循环,但它需要一点时间才能完成,可能需要100ms。
如果我选择顶部项目并使用向下箭头缓慢滚动项目,一切正常,但如果我按住箭头键,事件会过快触发,我会收到stackoverflow异常。
我考虑过在TreeView
放置一个计时器,所以SelectionChanged
事件只能每100毫秒左右开一次,但这看起来非常骇人听闻。有什么想法解决这个问题?
答案 0 :(得分:3)
我也见过像winforms这样的东西。我见过人们实现的一种方法是使用延迟事件处理程序。只有在指定时间段内选择了所述项目后才会触发。
所以工作方式是你有一个执行计时器的事件处理程序。每当触发selectionchanged事件时,计时器都会重置。你的计时器可能是500毫秒,所以如果在500毫秒后仍然选择了所选的值,它将触发你需要处理的实际事件代码。
不是说这是我在Windows窗体中看到的最佳方式。
答案 1 :(得分:1)
异步运行事件处理程序。最简单的方法如下:
void SelectionEventHandler(object sender, EventArgs e)
{
var ownerElement = sender as FrameworkElement; // this should be the TreeView itself
ThreadPool.QueueUserWorkItem(o => {
// Do stuff
ownerElement.Dispatcher.BeginInvoke(new Action(() => {
// Update UI in response to stuff being done
});
});
}
如果您使用类似The Reactive Framework的内容,那么您可以相当大地减少与ThreadPools等相关的错误。
您可能还会考虑使用它的Task<T>
类的并行任务库 - 您可以通过下载反应框架来获得.NET 3.5版本。
注意:异步运行处理程序应该停止堆栈溢出,但是当用户滚动列表时,它不会阻止处理程序运行1000次。如果你想这样做,你可以实现一个延迟计时器,或者如果你正在使用Reactive框架,它有一些功能可以为你做这种事情。