Windows 窗体单击事件不断重复

发布于 2024-08-12 07:13:19 字数 1190 浏览 6 评论 0原文

我在 Windows 窗体事件方面遇到了一个奇怪的问题。确切地说,这是一个 KryptonHeaderGroup 的 ButtonSpec Click 事件,但它也会发生在普通的 中System.Windows.Forms.Button

在单击事件中,用户界面被关闭(留下一个标签和一个取消按钮),然后根据先前的用户输入构建一个昂贵的 LINQ 查询,编译并执行。 foreach 中有 Application.DoEvents() 调用,它实际执行查询(它是 LINQ to 对象,所以它是惰性的)。这使用户能够按取消键,并且在 DoEvents 之后,测试取消标志并取消 foreach,并进行一些清理。到目前为止,一切都很好。

但是,当我在前几个结果出现后按下“取消”按钮(标签显示已有多少个结果)时,整个 Click 事件处理程序将重新启动!添加一些跟踪后,这似乎发生在前一个处理程序返回之前。换句话说,它发生在其中一个 DoEvents 调用中。当然,按钮不会再被按下。如果在事件处理程序中禁用该按钮,则不会发生这种情况。但由于按钮没有被按下,它不应该再次触发它的 Click 事件,不是吗?

我很困惑。显然,解决方法是禁用该按钮,但我想知道这里的实际问题是什么。如果在处理程序完成之前调用 DoEvents,事件处理程序是否可以重新启动?是否不建议/不允许在事件处理程序中调用 DoEvents?但是,由于事件驱动应用程序中的所有内容都是事件处理程序,因此您永远无法调用它:)

回答此问题可能需要的其他提示:

  • LINQ 查询在提供第一个结果之前(即在进行第一个 DoEvents 调用。
  • LINQ 查询在 GUI 线程中运行,因为允许用户访问其余应用程序是没有意义的,因为访问会干扰 GUI 和 LINQ 查询使用的底层 API。
  • 我知道我应该将 LINQ 查询加载到单独的应用程序域中并在那里执行它,以便能够卸载它。但典型用户只会运行几个不同的查询,并且生成的程序集会被缓存(对于相同的查询字符串)。
  • 如果我启用了断点(叹息 - 海森堡,有人吗?)或者如果我稍后在查询期间取消,则问题不再发生。

我很欣赏任何可以解释这种行为的东西,即使这只是猜测:)

I have a strange problem with a Windows Forms event. To be exact, it's a KryptonHeaderGroup's ButtonSpec Click event, but it also happens with a plain vanilla System.Windows.Forms.Button.

In the click event, the user interface is brought down (there's a label and a cancel button left), and then an expensive LINQ query is built from previous user input, compiled and then executed. There are Application.DoEvents() calls in the foreach which actually executes the query (it's LINQ to objects, so it's lazy). This enables the user to press cancel, and after the DoEvents, a cancel flag is tested and the foreach is cancelled, and some clean up happens. So far, so good.

However, when I press the Cancel button after the first few results come in (the label shows how many are already there), the whole Click event handler is restarted! After adding some traces, it seems that this happens before the previous handler returns. In other words, it happens in one of the DoEvents calls. The button is, of course, not pressed again. It does not happen if the button is disabled in the event handler. But since the button is not pressed, it should not fire its Click event again, should it?

I'm baffled. Obviously the workaround is to disable the button, but I'd like to know what may be the actual problem here. Can the event handler be restarted if DoEvents is called before the handler finishes? Is calling DoEvents not recommended / allowed in event handlers? But then, since everything is an event handler in an event-driven application, you could never call it :)

Additional hints that may be required to answer this question:

  • The LINQ query takes a long time initially before supplying first results, i.e. before the first DoEvents call is made.
  • The LINQ query runs in the GUI thread because it would not make sense to allow the user to access the rest application, because the access will interfere with the underlying API both the GUI and the LINQ query use.
  • I know I should load the LINQ query into a separate app domain and execute it there, to be able to unload it. But there will only be few different queries run by a typical user, and the resulting assembly is cached (for the same query string).
  • The problem no longer happens if I either have a break point enabled (sigh - Heisenberg, anyone?) or if I cancel later during the query.

I appreciate anything that would explain the behaviour, even if it's just speculation :)

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

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

发布评论

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

评论(1

不打扰别人 2024-08-19 07:13:19

DoEvents 将处理 GUI 消息,因此它将允许处理任何进一步的单击或消息。我建议您不要在事件处理程序中调用它,说实话我根本不会使用它。

来自 MSDN: 调用此方法可能会导致代码如果消息引发事件,则重新输入。

长期:

如果这是一个长时间运行的查询,您希望在后台线程上运行它并禁用该按钮。这是此类活动的一般模式。

DoEvents will process GUI messages so it will allow any further clicks or messages to be processed. I would recommend you don't call it in an event handler and to be honest I'd avoid using it at all.

From MSDN: Calling this method can cause code to be re-entered if a message raises an event.

Long term:

If this is a long running query you want to look at running it on a background thread and disable the button. This is the general pattern for this type of activity.

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