尝试做一个windows下定时访问数据的服务。正式工作可能一天运行一次。
为了测试设置了时间间隔为一分钟,timer elsped时间触发后也就是向一个文本文件里写一下当前时间。现在发现有个问题就是,这个时间逐渐在变,并不是间隔的很准2012-3-26 10:32:54------2012-3-26 10:32:54
2012-3-26 10:33:55------2012-3-26 10:33:55
2012-3-26 10:34:55------2012-3-26 10:34:55
2012-3-26 10:35:55------2012-3-26 10:35:55
2012-3-26 10:36:56------2012-3-26 10:36:56
2012-3-26 10:37:56------2012-3-26 10:37:56
2012-3-26 10:38:56------2012-3-26 10:38:56
2012-3-26 10:39:56------2012-3-26 10:39:56
2012-3-26 10:31:54------2012-3-26 10:31:54
2012-3-26 10:32:54------2012-3-26 10:32:54
2012-3-26 10:33:54------2012-3-26 10:33:54
2012-3-26 10:34:54------2012-3-26 10:34:54
2012-3-26 10:35:54------2012-3-26 10:35:54
2012-3-26 10:36:54------2012-3-26 10:36:54
2012-3-26 10:37:54------2012-3-26 10:37:54
2012-3-26 10:38:53------2012-3-26 10:38:53
2012-3-26 10:39:53------2012-3-26 10:39:53
2012-3-26 10:40:53------2012-3-26 10:40:53
2012-3-26 10:41:53------2012-3-26 10:41:53
2012-3-26 10:42:53------2012-3-26 10:42:53
2012-3-26 10:43:53------2012-3-26 10:43:53
2012-3-26 10:44:52------2012-3-26 10:44:52
2012-3-26 10:45:52------2012-3-26 10:45:52
2012-3-26 10:46:52------2012-3-26 10:46:52
2012-3-26 10:47:52------2012-3-26 10:47:52
2012-3-26 10:48:52------2012-3-26 10:48:52
2012-3-26 10:49:52------2012-3-26 10:49:52
2012-3-26 10:50:52------2012-3-26 10:50:52
2012-3-26 10:51:51------2012-3-26 10:51:51
2012-3-26 10:52:51------2012-3-26 10:52:51
2012-3-26 10:53:51------2012-3-26 10:53:51
2012-3-26 10:54:51------2012-3-26 10:54:51
2012-3-26 10:55:51------2012-3-26 10:55:51
2012-3-26 10:56:51------2012-3-26 10:56:51
2012-3-26 10:57:51------2012-3-26 10:57:51
2012-3-26 10:58:50------2012-3-26 10:58:50之后改成时间间隔为一个小时,发现也有问题,偏差更大2012-3-26 12:33:24------2012-3-26 12:33:24
2012-3-26 13:37:08------2012-3-26 13:37:08
2012-3-26 14:29:34------2012-3-26 14:29:34如上,开始还有些反复,后来就比较有规律的越来越短了。不知道这是因为什么?
其实我的这个应用对时间要求没有这么的高,但只是想弄明白,如果真有对时间要求必须控制在一秒左右的怎么解决?
以下是代码
Public Class Service1    Public Shared Function Validatordate(ByVal strDateA As String, ByVal strDateB As String) As Double
        Dim ts As TimeSpan = Convert.ToDateTime(strDateB) - Convert.ToDateTime(strDateA)
        Dim count As Double = ts.TotalSeconds * 1000
        Return count
    End Function    Protected Overrides Sub OnStart(ByVal args() As String)
       
        writeTest(System.Configuration.ConfigurationManager.AppSettings("serviceLog").ToString(), "Service is started")
        Dim sleeptime As Double = Validatordate(System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), System.DateTime.Now.ToString("yyyy-MM-dd ") + Configuration.ConfigurationManager.AppSettings("runTime").ToString)
        'Dim sleeptime As Double = Validatordate(System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), System.DateTime.Now.ToString("yyyy-MM-dd ") + "10:15")
        If sleeptime < 0 Then
            sleeptime += 24 * 60 * 60 * 1000
        End If        Dim t As System.Timers.Timer = New System.Timers.Timer(sleeptime)
        AddHandler t.Elapsed, AddressOf OnTimeEvent
        t.Interval = 1000 * 60 * 60
        t.AutoReset = True
        t.Enabled = True
        writeTest("c://service.log", "runend")    End Sub    Protected Overrides Sub OnStop()
        ' Add code here to perform any tear-down necessary to stop your service.
        writeTest(System.Configuration.ConfigurationManager.AppSettings("serviceLog").ToString(), "Service is stoped")
    End Sub
    Private Sub writeTest(ByVal path As String, ByVal message As String)
        Try
            If System.IO.File.Exists(path) Then
                Using wr As System.IO.StreamWriter = System.IO.File.AppendText(path)
                    wr.WriteLine(Date.Now.ToString() & "------" & message)
                    wr.Flush()
                    wr.Close()
                End Using
            Else                Dim wr As System.IO.StreamWriter = New System.IO.StreamWriter(path)
                wr.WriteLine(Date.Now.ToString() & "------" & message)
                wr.Flush()
                wr.Close()
            End If        Catch ex As Exception        End Try    End Sub    Private Sub OnTimeEvent(ByVal sender As Object, ByVal e As Timers.ElapsedEventArgs)
        writeTest("c://service.log", String.Format("{1,2}", "hi", e.SignalTime))
    End SubEnd Class

解决方案 »

  1.   

    你那个已经不错了,windows不是实时系统,而且还要受到环境的影响
      

  2.   

    timer本身就不太准确,你不要指望他能给你非常准确的判断,要实现准确的时间间隔,一般是新开线程,再线程内部进行操作:DateTime dt1=DateTime.Now;while(isStop)
    {
       DateTime dt2=DateTime.Now;
       if(dt2-dt1>=你的时间间隔)
       {
            dt1=dt2;
           //执行你的任务
        }
        else
           Thread.Sleep(1000);//调整这里的数值可以保证你精度,越短精度越高
    }
      

  3.   

    windows不是实时系统,timer不可能精确的
      

  4.   

    请问能说的具体些吗?你的方法是一直使用循环判断对比datetime时间来记时?
    新开线程为什么会对时间影响较小?
      

  5.   

    thread里不停while,进行时间比对,一旦发现时间间隔达到,就执行,实时性比较高。
    timer的精确度差,这是基于消息机制的,消息是有延迟的,当然也可能提前。
      

  6.   

    原来从实现方法上造成了 timer不准
      

  7.   

    之前写过一个服务,里面有两个定时器,一个半分钟监控,一个五分钟调用远程WS发送并校验数据。从秒上看时间都比较准。可能你的代码逻辑没控制好导致定时器重入或者别的问题吧不过MSDN上明确地说了,Timer是不精确的,原因LS已经说了