使用Timer类的跨线程操作错误

时间:2015-02-24 13:42:54

标签: .net vb.net winforms timer

我的代码中显示上述错误。当我使用Windows窗体的计时器时,我能够成功运行我的应用程序。现在我已经改为system.timers,我不知道我做错了什么。我正在实现IMessageFilter来监听鼠标/键盘移动并在有交互时重新启动计时器。如果没有交互,请隐藏表单。拜托,有人可以帮帮我吗?我正在使用VB.Net,这是我正在使用的代码:

从表单加载

Application.AddMessageFilter(Me)
timerTest= New System.Timers.Timer()
AddHandler timerTest.Elapsed, AddressOf OnTimedTestEvent
timerTest.Enabled = True

实施IMessageFilter

Public Function PreFilterMessage(ByRef m As Message) As Boolean Implements IMessageFilter.PreFilterMessage

            If (m.Msg >= &H100 And m.Msg <= &H109) Or (m.Msg >= &H200 And m.Msg <= &H20E) Then
                timerTest.Stop()
                timerTest.Interval = 30000
                timerTest.Start()
                End If
            End If

    End Function

事件触发器

Private Sub OnTimedTestEvent(source As Object, e As ElapsedEventArgs)

        timerTest.Stop()
        HideForm()

    End Sub

隐藏表单

Private Sub HideForm()

            Me.Visible = False <--- getting error here
End Sub

1 个答案:

答案 0 :(得分:1)

只允许UI线程更改UI对象。这是WinForms的一个已知限制。

Forms.Timer课程将在UI的消息泵中保持代码运行,这意味着您不必担心跨线程调用。但是,Timers.Timer可以使用自己的主题。

要获得所需的行为,您可能希望继续使用WinForm的Forms.Timer课程或将HideForm()方法更改为:

Private Sub HideForm()
    If Me.InvokeRequired Then
        Me.Invoke(New Action(Sub() Me.HideForm()))
    Else
        Me.Visible = False
    End If
End Sub

InvokeRequired布尔属性检查代码当前是否在除UI之外的其他线程上运行。如果是,您可以在Invoke方法中调用您想要的任何代码。

您可能还想查找其他计时器课程,具体取决于您(当前或将来)的需求。

来自MSDN

  

.NET Framework类库包含四个名为Timer的类,每个类都提供不同的功能:

     
      
  • System.Timers.Timer ,它会定期触发事件并在一个或多个事件接收器中执行代码。该类旨在用作多线程环境中的基于服务器或服务组件;它没有用户界面,在运行时不可见。
  •   
  • System.Threading.Timer ,它定期在线程池线程上执行单个回调方法。回调方法是在实例化定时器时定义的,无法更改。与System.Timers.Timer类一样,此类旨在用作多线程环境中的基于服务器或服务组件;它没有用户界面,在运行时不可见。
  •   
  • System.Windows.Forms.Timer ,一个Windows窗体组件,用于触发事件并定期在一个或多个事件接收器中执行代码。该组件没有用户界面,专为在单线程环境中使用而设计。
  •   
  • System.Web.UI.Timer ,一个定期执行异步或同步网页回发的ASP.NET组件。
  •   

希望这有帮助。