2

我的印象是 System.Timers.Timer 创建了自己的线程,并且 Microsoft 建议使用这种类型的计时器来执行更准确计时的任务(与在 UI 线程中运行的 Windows.Forms.Timer 相对)。

下面的代码(我认为)应该可以复制并粘贴到具有空表单的项目中。在我的机器上,我无法让 tmrWork 以每秒 60 次以上的速度滴答作响,而且它非常不稳定。

Public Class Form1

    Private lblRate As New Windows.Forms.Label
    Private WithEvents tmrUI As New Windows.Forms.Timer
    Private WithEvents tmrWork As New System.Timers.Timer

    Public Sub New()
        Me.Controls.Add(lblRate)

        InitializeComponent()
    End Sub

    Private StartTime As DateTime = DateTime.Now
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) _
        Handles MyBase.Load
        tmrUI.Interval = 100
        tmrUI.Enabled = True
        tmrWork.Interval = 1
        tmrWork.Enabled = True
    End Sub

    Private Counter As Integer = 0
    Private Sub tmrUI_Tick(sender As Object, e As System.EventArgs) _
        Handles tmrUI.Tick
        Dim Secs As Integer = (DateTime.Now - StartTime).TotalSeconds
        If Secs > 0 Then lblRate.Text = (Counter / Secs).ToString("#,##0.0")
    End Sub

    Private Sub tmrWork_Elapsed(sender As Object, e As System.Timers.ElapsedEventArgs) _
        Handles tmrWork.Elapsed
        Counter += 1
    End Sub
End Class

在这个特殊的简单案例中,将所有内容都放入 tmrUI 将产生相同的性能。我想我从来没有尝试过让 System.Timers.Timer 跑得太快,但这种性能对我来说太糟糕了。我编写了自己的类以在硬件中使用高性能计时器,但似乎应该有一个内置的计时器可以做到,比如每秒 100 个滴答声?

这里发生了什么?

4

1 回答 1

-1

要接近 100Hz,请尝试使用 AutoResetEvent 的类似方法。

Private Sub tmrWork()
    'start this as a background thread
    Dim tmr As New Threading.AutoResetEvent(False)
    Dim stpw As Stopwatch = Stopwatch.StartNew
    Const interval As Integer = 10 'the interval
    '
    '
    Do 'timer
        stpw.Stop()
        If stpw.ElapsedMilliseconds > interval Then
            tmr.WaitOne(interval) 'the interval
        Else
            tmr.WaitOne(CInt(interval - stpw.ElapsedMilliseconds)) 'the interval
        End If
        stpw.Restart()
        '
        'code to execute when 'timer' elapses
        '

    Loop
End Sub

这是一个测试,表明根据您在循环中的操作,可以以 100Hz 的频率触发代码。

Private Sub tmrWork()
    Dim tmr As New Threading.AutoResetEvent(False)
    Dim stpw As Stopwatch = Stopwatch.StartNew
    Const interval As Integer = 10 'the interval
    'for testing
    Dim cts As New List(Of Long)
    '
    '
    Do 'timer
        tmr.WaitOne(interval) 'wait for the interval
        cts.Add(stpw.ElapsedMilliseconds) 'add elapsed to list
        stpw.Restart() 'restart
        If cts.Count >= 500 Then 'five second test
            Debug.WriteLine(String.Format("Avg: {0},  Min: {1},  Max: {2}", cts.Average, cts.Min, cts.Max))
            Stop
        End If
    Loop
End Sub

Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    Dim t As New Threading.Thread(AddressOf tmrWork)
    t.IsBackground = True
    t.Start()
End Sub

对于汉斯·皮森特

Platform Timer Resolution:Platform Timer Resolution 默认的平台定时器分辨率为 15.6ms (15625000ns),应在系统空闲时使用。如果定时器分辨率增加,处理器电源管理技术可能无效。由于多媒体播放或图形动画,计时器分辨率可能会增加。当前定时器分辨率(100ns 单位) 100000 最大定时器周期(100ns 单位) 156001

Platform Timer Resolution:Outstanding Timer Request 程序或服务请求的计时器分辨率小于平台最大计时器分辨率。请求周期 100000 请求进程 ID 452 请求进程路径 \Device\HarddiskVolume3\Windows\System32\svchost.exe

于 2013-10-24T17:51:55.580 回答