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

发布于 2024-08-20 07:34:22 字数 334 浏览 6 评论 0原文

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

如果我选择顶部项目并使用向下箭头缓慢滚动项目,则一切正常,但如果我按住箭头键,则事件触发得太快,并且出现 stackoverflow 异常。

我考虑过在 TreeView 中放置一个计时器,这样 SelectionChanged 事件只能每 100 毫秒左右触发一次,但这看起来很黑客。有解决这个问题的想法吗?

I have a TreeView with 1000 items. When I select an item, the TreeView fires an event so I can update something in my GUI. The event handler is non recursive and has no loops, but it does take a little bit of time to complete, maybe 100ms.

If I select the top item and use the down arrow to scroll through items slowly, everything works fine, but if I hold down the arrow key, the event fires too quickly and I get a stackoverflow exception.

I thought about putting a timer in the TreeView so the SelectionChanged event can only fire every 100ms or so, but that seems very hackish. Any ideas for fixing this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦与时光遇 2024-08-27 07:34:23

异步运行事件处理程序。最简单的方法如下:

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

        });
    });
}

如果您使用类似 反应式框架 那么你就可以大大减少与线程池等相关的麻烦。

您还可以考虑使用并行任务库及其 Task 类 - 您可以通过下载反应式框架来获取 .NET 3.5 版本。

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

Run the event handler asynchronously. The simplest way of doing this is as follows:

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

        });
    });
}

If you use something like The Reactive Framework then you can cut down the cruft involved with ThreadPools, etc quite considerably.

You might also consider the Parallel Task library with it's Task<T> class - You can get a .NET 3.5 version by downloading the reactive framework.

NOTE: Running the handler asynchronously should stop the Stack Overflow, however it won't stop the handler from running 1000 times when the user rolls down the list. If you want to do that you can either implement a delay timer, or if you're using the Reactive framework, it has some features which can do this kind of thing for you.

浮华 2024-08-27 07:34:22

我也见过类似的事情发生在 winform 上。我见过人们实现的一种方法是使用延迟事件处理程序。这样它仅在选择所述项目达指定时间段后才触发。

因此,工作方式是有一个执行计时器的事件处理程序。每当选择更改事件被触发时,计时器就会重置。您的计时器可能是 500 毫秒,因此如果 500 毫秒后仍选择所选值,它将触发您需要处理的实际事件代码。

并不是说这是最好的方法,只是我在 Windows 窗体中看到它处理的一种方法。

I've seen stuff like this happen on winforms as well. One way that I have seen people implement is to have a delayed event handler. Such that it fires only after the said item has been selected for a specified time period.

So the way that works is you have an event handler that executes a timer. The timer gets reset whenever the selectionchanged event is fired. Your timer would be maybe 500ms so if the selected value is still selected after 500ms it will then fire your actual event code you need handled.

Not saying this is the best way just a way I have seen it handled in windows forms.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文