【问题标题】:VB.NET UserControl Why is MouseMove event async?VB.NET UserControl 为什么 MouseMove 事件是异步的?
【发布时间】:2014-04-11 11:49:56
【问题描述】:

我在 VB.NET 中创建了一个用户控件,并且我在 MouseMove 事件中做了一些相当耗时的工作。

我预计 MouseMove 事件会排队。

但我包含了一个陷阱,它表明 MouseMove 事件确实没有排队,我认为它是异步工​​作的。

Private _bInproc As Boolean = false

Private Sub ucGrid_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove

    If _bInproc Then
        Stop 'This should never be reached if MouseMove events were always queued, I think
     End If

    _bInproc = True

    doMousePointerMoveStuff(e.X, e.Y)

    _bInproc = False

End Sub

有没有人看到我可能犯的任何错误,或者有没有人知道我的情况可能会变成异步的情况??

【问题讨论】:

  • 你有明确调用ucGrid_MouseMove方法的代码吗?您是否有任何代码明确引发UserControlMouseMove 事件?我怀疑doMousePointerMoveStuff 中的某个地方正在做这些事情之一。
  • 我在 doMousePointerMoveStuff 中调用 Me.Invalidate(somechangedregion)。但这不应该造成这种影响,不是吗?
  • @StevenDoggart 你是对的......我正在做一些介于两者之间的事情:我正在使用一个 Application.DoEvents 它破坏了它。你能把你的评论作为回复吗?您能否还补充一点,在“停止”之后按 f11 有助于找出导致不平衡的原因?因为这样我就进入了具有 DoEvents 的函数。

标签: vb.net user-controls mousemove


【解决方案1】:

诸如 MouseMove 之类的 WinForm 事件不是多线程的(异步)。事件总是以串行方式在同一个 UI 线程中引发。但是,仅当事件由窗口消息循环 (WndProc) 引发时才适用。这是引发事件的典型方式,但您可以在自己的代码中,在第一个事件处理完毕之前重新引发事件。有几种方法可以发生这种情况。首先,在事件处理程序中,您可以递归调用相同的事件处理程序方法。其次,在事件处理程序中,您可以再次引发相同的事件,这将导致立即再次调用事件处理程序。第三,您可以调用 DoEvents,这将导致消息循环立即处理所有可能再次引发相同事件的排队窗口消息。所有这些事情都是令人困惑和出乎意料的,所以我不鼓励做任何这些事情。这是 DoEvents 如此不受欢迎的主要原因之一。为了弄清楚它是从哪里调用的,只需在事件处理程序中放置一个断点,并在每次调用时查看调用堆栈。

【讨论】:

    【解决方案2】:

    WinForms 中的事件从不异步,它们总是发生在 UI 线程上。这就是您能够更改其中其他控件的属性的原因。否则你会得到跨线程操作异常。

    现在因为它们与 UI 线程同步,所以不能有任何事件队列。您不能从 UI 线程发送另一个事件,即通过移动鼠标,因为 UI 线程当前正在处理事件处理程序。

    您可以拥有自己的异步事件处理程序,在这种情况下您负责处理其中的线程同步。

    希望这是有道理的。如果没有,请在下面的 cmets 中询问。

    【讨论】:

    • 你是说我所经历的事情可能不会发生,对吧?
    • @tmighty:在正常情况下不应该发生,是的。但它正在发生的事实仅意味着您没有讲述代码结构背后的全部故事。我假设您获得的体验是一致的,即发生在全新的操作系统安装上,没有/最少运行其他应用程序。
    猜你喜欢
    • 2013-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多