在服务中每隔指定时间运行方法而不重复 [英] Run method every specified time within a service without repeating

查看:29
本文介绍了在服务中每隔指定时间运行方法而不重复的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Windows 服务,如下所示:

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

你能解释一下为什么我在下午 3 点 44 分 15 分收到两个输入吗?我认为计时器事件 OnTimer 会暂停,直到之前的 OnTimer 作业完成,然后时间会有所不同,并且不会在同一时间内进入.怎么了?

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

进一步讨论:

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

推荐答案

显示的时间被截断了,而且计时器也不是那么精确(分辨率偶尔以几十毫秒为单位,更不用说可能出现的延迟了多任务处理).因此,这可能只是计时器事件触发两次的情况,几乎相隔一秒,但在同一显示秒内.

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.

此外,根本无法保证前面的事件处理程序将完成其工作,除非该事件是在同一线程上触发的.也就是说,使用旧的DoEvents 之类的东西意外地允许可重入事件并不难.而且,事实上,该类甚至被设计为在线程池线程上运行多线程、潜在地触发事件,即或多或少地随意,除非提供了 SynchronizingObject.(事实并非如此.)

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.

我建议您专门跟踪当天事件中是否已达到给定时间,如果尚未达到,则允许事件通过.显然,同步访问以防万一,可能在 Timer 上使用 SynchronizingObject.

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.

这篇关于在服务中每隔指定时间运行方法而不重复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆