.net - System.Timers.Timer(.NET)真的很慢吗?

标签 .net vb.net multithreading timer

我的印象是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次滴答声?

这里发生了什么?

最佳答案

要获得接近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

对于汉斯·皮森(Hans Pissant)

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

平台计时器分辨率:未完成的计时器请求程序或服务请求的计时器分辨率小于平台最大计时器分辨率。请求的时间段100000正在请求的进程ID 452正在请求的进程路径\Device\HarddiskVolume3\Windows\System32\svchost.exe

关于.net - System.Timers.Timer(.NET)真的很慢吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19571739/

相关文章:

.net - 定义具有相同名称和不同数量类型参数的泛型类 (C++/CLI)

c++ - 如何监控我生成的进程中的事件?

html - 如何在 Web 浏览器(html 格式)中打开本地 .msg 文件并显示嵌入的图片

sql - 如何在 SQL Server 中选择“正确使用 "between"”?

c# - MSBuild BuildInParallel,无法运行的自定义任务生成过程

c++ - Native 与 Protothreads,哪个更容易?

ios - 无法验证...的代码签名无法在我的 iPhone 上安装应用程序

asp.net - 句柄子句需要在包含类型或其基类型之一中定义的 WithEvents 变量

java - android surfaceview runnable 延迟的正确方法?

c# - 如何检查字符串是 "string"还是 RegEx?