在单个计时器中处理多重计时器

时间:2016-01-27 09:45:22

标签: .net vb.net timer

我的表单上有大约20个计时器,所有计时器都有不同的间隔。 例如,一个间隔为25,一个间隔为100,但有些间隔也有“不规则”间隔,如43.

我想只有一个计时器并处理其Tick事件中的所有内容。

例如:

Private Sub _TmrAll_Tick(sender As Object, e As EventArgs) Handles _TmrAll.Tick

    _iTimer += 25

    If _iTimer Mod 25 = 0 Then
        pHandleClickDelayRepeat()
    End If

    If _iTimer Mod 100 = 0 Then
        pHandleSkype()
    End If

    If _iTimer Mod 43 = 0 Then 'this of course would not work with my current approach
        pHandleMouse()
    End If

它认为我目前的方法并不是很好,因为我不能轻易处理这些不规则的间隔。

有没有人更好地了解如何做到这一点?

谢谢。

5 个答案:

答案 0 :(得分:0)

问题是,你总是在检查之前添加值 应该完成。

_iTimer += 25

必须写在If条件下。

答案 1 :(得分:0)

假设_iTimer是一个全局变量,用于计算循环,你应该增加1而不是25.否则你将永远不会达到你的“不规则”间隔。您应该将计时器间隔更改为1000(基于1秒)并将1递增1(_iTimer + = 1)。

答案 2 :(得分:0)

您只需要一个计时器,并将间隔设置为所有间隔的最大除数(没有余数)。

在你的情况下,43只能除以43或1.你不能使用43,因为这不是25的除数,所以你唯一的选择是1.这意味着当它什么也不做的时候它会被激活很多次但这并不重要。

因此,只需跟踪区间变量(您可以使用静态变量来保持范围尽可能小)。像这样:

Private Sub _TmrAll_Tick(sender As Object, e As EventArgs) Handles _TmrAll.Tick
    Static intervalCount As Integer = 0

    intervalCount += 1

    If intervalCount Mod 25 = 0 Then
        pHandleClickDelayRepeat()
    End If

    If intervalCount Mod 100 = 0 Then
        pHandleSkype()
    End If

    If intervalCount Mod 43 = 0 Then 
        pHandleMouse()
    End If
End Sub

答案 3 :(得分:0)

我建议您使用Microsoft的Reactive Framework(称为Rx)。只是NuGet“Rx-WinForms”。

这是我的代码:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    Dim cs = New ControlScheduler(Me)

    Dim subscription1 =
        cs.SchedulePeriodic(
            TimeSpan.FromMilliseconds(25.0),
            Sub() pHandleClickDelayRepeat())

    Dim subscription2 =
        cs.SchedulePeriodic(
            TimeSpan.FromMilliseconds(100.0),
            Sub() pHandleSkype())

    Dim subscription3 =
        cs.SchedulePeriodic(
            TimeSpan.FromMilliseconds(43.0),
            Sub() pHandleMouse())

End Sub

Rx为我们提供了一堆可以直接使用的调度程序。我选择了ControlScheduler来确保将预定事件推送到UI线程。

ControlScheduler实际上是您应用中的单个计时器。

您可以直接使用调度程序,也可以单独根据间隔创建自己的可观察对象,并在ControlScheduler上观察它们。

    Dim cs = New ControlScheduler(Me)

    Dim subscription1 =
        Observable _
            .Interval(TimeSpan.FromMilliseconds(25.0)) _
            .ObserveOn(cs) _
            .Subscribe(Sub() pHandleClickDelayRepeat())

    Dim subscription2 =
        Observable _
            .Interval(TimeSpan.FromMilliseconds(100.0)) _
            .ObserveOn(cs) _
            .Subscribe(Sub() pHandleSkype())

    Dim subscription3 =
        Observable _
            .Interval(TimeSpan.FromMilliseconds(43.0)) _
            .ObserveOn(cs) _
            .Subscribe(Sub() pHandleMouse())

第二种方法可以让你做各种很酷的查询。

    Dim query =
        From n In Observable.Interval(TimeSpan.FromMilliseconds(193.0))
        Where n * 2 Mod 3 = 1
        Select "Foo" & n * 5

    Dim subscription4 = query.ObserveOn(cs).Subscribe(Sub(x) Me.Label1.Text = x)

每当您想要停止其中一个预定的操作或观察者订阅时,您只需在其上调用.Dipose(),如下所示:

    subscription1.Dispose()
    subscription2.Dispose()
    subscription3.Dispose()
    subscription4.Dispose()

答案 4 :(得分:0)

似乎您只需要确定哪个计时器触发事件​​以执行该计时器的特定任务。如果是这种情况,那么您应该只设置计时器的Tag属性(在设计时或以编程方式创建Timer),并在事件触发时执行触发事件处理程序的计时器所需的代码。 /> 无需使用定时器间隔来识别定时器。

Private Sub _TmrAll_Tick(sender As Object, e As EventArgs) Handles _TmrAll.Tick

    Dim tm = CType(sender, System.Windows.Forms.Timer)

    Select Case tm.Tag.ToString
        Case "Delay"
            pHandleClickDelayRepeat()
        Case "Skype"
            pHandleSkype()
        Case "Mouse"
            pHandleMouse()
        Case Else
            Debug.WriteLine("Tag not expected")
     End Select
End Sub