Run method every specified time within a service without repeating

∥☆過路亽.° 提交于 2019-12-24 14:08:20

问题


I have a Windows service as shown below:

Protected Overrides Sub OnStart(ByVal args() As String)
    Dim timer As System.Timers.Timer = New System.Timers.Timer()
    timer.Interval = 1000       '1 sec
    AddHandler timer.Elapsed, AddressOf Me.OnTimer
    timer.Start()
End Sub

Private Sub OnTimer(sender As Object, e As Timers.ElapsedEventArgs)
    Dim Time As String = DateTime.Now.ToString("hh:mm:ss tt")
    If Time = "01:58:15 PM" Or Time = "02:42:15 PM" Or Time = "02:43:15 PM" _
            Or Time = "03:44:15 PM" Or Time = "06:00:15 PM" _
            Or Time = "12:00:15 AM" Or Time = "05:00:15 AM" Then
        Dim path As String = Application.StartupPath & "\test.log"
        Dim strFile As String = String.Format(path, _
                DateTime.Today.ToString("dd-MMM-yyyy"))
        File.AppendAllText(strFile, String.Format("Message at-- {0}{1}", _
                DateTime.Now, Environment.NewLine))
    End If
End Sub

Can you explain to me why I got two inputs for 3:44:15 PM? I thought timer event OnTimer is on hold till previous OnTimer job finished then time would be different and it would not go in within same time. What's wrong?

Message at-- 1/13/2015 3:44:15 PM
Message at-- 1/13/2015 3:44:15 PM
Message at-- 1/14/2015 12:00:15 AM
Message at-- 1/14/2015 5:00:15 AM

For further discussion:

Private Sub OnTimer(sender As Object, e As Timers.ElapsedEventArgs)
    RemoveHandler timer.Elapsed, AddressOf Me.OnTimer
    Dim Time As String = DateTime.Now.ToString("hh:mm:ss tt")
    If Time = "01:58:15 PM" Or Time = "02:42:15 PM" Or Time = "02:43:15 PM" _
            Or Time = "03:44:15 PM" Or Time = "06:00:15 PM" _
            Or Time = "12:00:15 AM" Or Time = "05:00:15 AM" Then
        Dim path As String = Application.StartupPath & "\test.log"
        Dim strFile As String = String.Format(path, _
                DateTime.Today.ToString("dd-MMM-yyyy"))
        File.AppendAllText(strFile, String.Format("Message at-- {0}{1}", _
                DateTime.Now, Environment.NewLine))
    End If
    AddHandler timer.Elapsed, AddressOf Me.OnTimer
End Sub

回答1:


The time being displayed is truncated, and timers are not all that amazingly precise (resolution is occasionally measured in tens of milliseconds, never mind the delays that can come in with multitasking). Therefore it is probably just a case where the timer event fired twice, almost a second apart, but within the same displayed second.

Furthermore, there is no guarantee at all that a preceding event handler will have finished its work, except insofar as the event is fired on the same thread. Which is to say, it's not difficult to accidentally allow reentrant events with stuff like the old DoEvents. And, in fact, the class is even designed to run multi-threaded, potentially firing events on threadpool threads, i.e. more or less willy-nilly, unless a SynchronizingObject is supplied. (Which it wasn't.)

If you want to check the resolution for your system, you'll have to dig into the example given in the docs for Interval.

I recommend you specifically track whether a given time has yet been reached in the event for the current day, and if it hasn't, allow the event to go through. Obviously, synchronize access to this just in case, probably using SynchronizingObject on the Timer.



来源:https://stackoverflow.com/questions/27937815/run-method-every-specified-time-within-a-service-without-repeating

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!