如果SelectionChanged事件触发太快,WPF Treeview stackoverflow?

时间:2010-02-08 21:09:26

标签: c# wpf treeview stack-overflow

我有一个TreeView,包含1000个项目。当我选择一个项目时,TreeView会触发一个事件,以便我可以在GUI中更新某些内容。事件处理程序是非递归的,没有循环,但它需要一点时间才能完成,可能需要100ms。

如果我选择顶部项目并使用向下箭头缓慢滚动项目,一切正常,但如果我按住箭头键,事件会过快触发,我会收到stackoverflow异常。

我考虑过在TreeView放置一个计时器,所以SelectionChanged事件只能每100毫秒左右开一次,但这看起来非常骇人听闻。有什么想法解决这个问题?

2 个答案:

答案 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的内容,那么您可以相当大地减少与T​​hreadPools等相关的错误。

您可能还会考虑使用它的Task<T>类的并行任务库 - 您可以通过下载反应框架来获得.NET 3.5版本。

注意:异步运行处理程序应该停止堆栈溢出,但是当用户滚动列表时,它不会阻止处理程序运行1000次。如果你想这样做,你可以实现一个延迟计时器,或者如果你正在使用Reactive框架,它有一些功能可以为你做这种事情。