2010-10-01 83 views
4

有什么方法可以临时禁用Windows窗体上的所有事件?在Windows窗体上禁用所有事件

我有处理副线程处理由主线程上的事件损坏的情况。 (主线程事件正在修改数据绑定到辅助线程使用的变量的控件的内容。)寻找一种方法来“锁定”表单,直到辅助线程处理完成。 (显然,将处理移动到主线程会执行此操作 - 但它也会“冻结”UI,这不是我想要的)。

回答

1

非常感谢您的优质帮助。真的帮助决策过程。赞扬每个人。结束使用锁定。 (即每个事件处理程序开始时的if语句会在继续执行之前检查锁定状态。)从技术上来说,单调乏味并不是所有这些“酷”,但很简单,它的工作原理。

+0

简单而有效的解决方案。对于“通用”事件处理程序,不必那么乏味。 – chris 2012-05-22 10:09:25

1

在窗体上阻塞事件可以有效地冻结UI。事件是消息泵中标准消息处理的一部分 - 停止事件会冻结UI。

在您的工作正在处理时(例如禁用单个按钮等)禁用UI功能会更好,然后在完成后重新启用它们。这将允许进行正常活动,但防止用户触发按钮点击等

+0

问题是导致我问题的事件仍然在禁用的UI元素上启用。 (不管你信不信,当用户与残疾人互动时,很多事件仍然会发生。)但是我喜欢你在哪里接受这个事情。 – Jeff 2010-10-04 13:03:50

+0

@Jeff:哪个事件导致你的问题?你总是可以进一步采取这一步 - 而不是仅仅禁用/启用控件,做一个小例程,取消订阅并重新订阅控件上的事件......(我已经为鼠标悬停,窗体代码,例如。) – 2010-10-04 17:25:10

2

一些不同的选择应该让你解决这个问题:

  • 禁用任何控件,将触发该事件是不是线程安全的,
  • 使用同一对象上的监视器锁定所有修改变量或所有事件提升程序的代码,或者分离并重新附加所有处理程序。

我会去第一个选项,可能与光标设置为沙漏和/或在状态栏中设置消息。它很简单,有效,并且不会导致实际的UI冻结。我会避免第三种选择,因为它会在你的表单工作时“破坏”你的表单的行为。第二个选项的功效取决于你如何实施它;它可以很容易地冻结用户界面,这是你不想做的事情。

+0

这并不能解决问题。事件处理程序可能已经开始运行。标准线程竞赛。 – 2010-10-01 16:27:17

+0

然后使用单个对象引用上的锁来锁定所有触及绑定到控件的数据的代码;我提到这是另一种选择。但是,它可能会阻塞UI线程。 – KeithS 2010-10-01 16:46:05

2

这是一个标准的线程问题。即使你可以阻止事件,但是很难做到,它仍然不能解决问题。因为事件处理程序可能已经启动,但尚未完成,直到您想要开始阻止为止。

它有一个标准的解决方案,使用锁关键字。

如果这样做不实际,因为用户需要更改多个控件才能再次运行查询,那么您需要先终止正在运行的线程。例如BackgroundWorker.CancelAsync。如果这是不实际的,因为取消查询需要很长时间,那么您需要在查询运行时将控件Enabled属性设置为false。

1

如果要禁止所有由PostMessage产生的事件,则可以实现IMessageFilter接口并使用AddMessageFilter

这可能会陷入您感兴趣的所有事件。它不会陷入一切,例如由SendMessage产生的事件。为了捕获绝对的一切,你将需要一个thread-specific application hook

请注意,这将导致UI完全冻结,这可能不是你想要的。更好的应用可能是当你的后台工作正在进行时,拦截适当的事件并抑制不想要的行为。