Windows Service中Timer计时异常问题求助
我编写的Timer代码在Windows Forms客户端(VB.NET)中运行完全正常:整点整分启动,之后每10秒触发一次,全天稳定。但相同代码在Windows Service中却无法正常工作:无法保持每10秒触发,全天运行后会出现数秒延迟。由此可见,Windows客户端与Windows Service对Timer的处理机制存在明显差异(目前尚未明确原因)。
我在Windows Service中实现了@dbasnett提供的代码,并运行了一整夜,运行结果显示:该Timer能够整点整分启动,之后全天每10秒稳定触发一次。其中NDD_Zeit是数据存储到SQL Server的时间戳,NDD_TradeTime_US是经纪商JSON API返回的实际交易时间。通常数据会精确每10秒存储/获取一次,极少情况下会出现1秒间隔,但仅单次出现,而原Timer会持续漂移,全天累计可达十余秒。
在此特别感谢@dbasnett的分享、支持与耐心,我将标记其回答为解决方案。若您在Windows Service中需要精确Timer且遇到问题,可采用@dbasnett回答中的最新代码。
我正在开发一款自动交易机器人(通过API对接经纪商实现自动交易)。该机器人的Windows客户端每10秒通过API获取实时数据,执行买卖操作。为便于测试(修改机器人代码后快速验证效果),我开发了一款Windows Service,同样每10秒获取数据并存储到SQL Server,以便使用历史数据进行模拟测试。
核心问题在于客户端与Service的数据不同步:例如客户端在10:02:13获取数据,而Service在10:02:19获取同一数据,这会导致不同的逻辑执行结果。
为此我希望将Timer触发时间同步到同一秒,于是实现了两个Timer:
- 1秒间隔的Timer,用于触发“实际工作”的10秒Timer(目标是整点整分启动)
- 10秒间隔的Timer,执行实际的数据获取与存储工作
具体逻辑为:先启动1秒Timer,等待时间到整分的50秒时,启动10秒Timer,使其在hh:mm:00(整分)启动,之后每10秒触发一次。
在Windows客户端中该逻辑运行完美:Timer整分启动,之后每10秒触发一次(如10:02:00、10:02:10等),全天稳定。
但相同代码在Windows Service中却无法正常工作(原因不明):1秒Timer能正确在整分的50秒启动10秒Timer(可通过Windows事件日志确认),但10秒Timer首次触发时间却为10:02:03,之后为10:02:13,且运行时间越久,漂移越严重,例如后续会变为11:02:04等。
备注:
- Windows客户端与Service运行在同一机器(时钟通过互联网同步)
- 也曾在服务器上运行Service,结果相同
- 10秒Timer中的工作(API查询数据并存储到SQL Server)耗时不到1秒
我还尝试将启动时间改为整分的47秒,仍然无法让10秒Timer在整分启动,这让我更加困惑。
Timer定义(类中)
Public TimerDatenAbruf As New System.Timers.Timer() ' 执行工作的10秒Timer Public TimerSekundenSync As New System.Timers.Timer() ' 启动10秒Timer的1秒Timer
Timer初始化(OnStart()中)
TimerDatenAbruf.Interval = 10 * 1000 ' 10秒间隔 TimerSekundenSync.Interval = 1 * 1000 ' 1秒间隔 ' 添加事件处理器并启动1秒Timer AddHandler TimerSekundenSync.Elapsed, AddressOf SekundenTimerEvent TimerSekundenSync.Enabled = True TimerSekundenSync.Start() AddHandler TimerDatenAbruf.Elapsed, AddressOf TimerDatenAbrufTimerEvent
1秒Timer事件代码(SekundenTimerEvent())
Private Sub SekundenTimerEvent(source As Object, e As ElapsedEventArgs) ' 同步到整分 Dim dtTimeStampAktuell As DateTime = System.DateTime.Now Dim iSekunden As Integer = dtTimeStampAktuell.Second If iSekunden = 50 Then If Not TimerDatenAbruf.Enabled Then ' 仅在未运行时启动 TimerDatenAbruf.Start() ' 启动10秒Timer TimerSekundenSync.Stop() ' 停止1秒Timer End If End If End Sub
更新1
我在Windows客户端中实现了您的代码,结果显示:左侧原Timer代码与右侧您的代码均能正确启动,运行12分钟及21分钟后均保持精确计时。如前所述,客户端的Timer方案运行9小时后仍稳定,但Service中的Timer在运行约16分钟后开始漂移,可见Windows客户端与Service对Timer的处理存在差异。
我尝试在Service中实现您的代码,但遇到多个问题:数据通过异步JSON API(使用HttpClient)获取,因此调用需被await,且方法需标记为async。但一旦标记为async,就无法定义静态变量;此外Me.BeginInvoke在Windows Service中不可用(仅Windows Forms应用支持)。若您能提供适用于Windows Service的正确代码,我将立即测试,感谢!
更新2
数据在异步函数NasdaqDatenAbrufen()中获取,返回Task。我无法await该任务,我认为应该用"await t";若不用await,VS会提示“任务未被等待”...感谢!
内容的提问来源于stack exchange,提问作者FredyWenger

