在.NET中的某个小时执行某些功能

时间:2014-04-07 08:19:47

标签: .net vb.net timer scheduled-tasks

This post和许多其他人提出了Windows任务计划程序,但出于各种原因,这对我来说不是一个选项。

所以我有下面显示的代码,它运行得相当好(它已经运行了几个月)。但是我仍有一些怀疑让我的灵魂磨砺,因为我的其他系统都基于这个代码:

  • 是否确实是我在.NET代码中触发预定功能的唯一选项,正如所有其他帖子所暗示的那样?它看起来有点像拼凑而成。
  • 是否有跳过元素的概率?我的意思是:在执行时间等方面,我认为可能会以某种方式跳过执行时间检查的1秒间隔。
  • 有没有更好的方法来解决“频率分钟”部分?设置baseDate让我有点困惑......此外,它似乎只在小时设置为尽可能接近00:00时才起作用(例如:由于某种原因“每12小时18:00”将不会执行早上6点用当前代码)

鉴于我的技能,我认为这个主题有点过于复杂,所以我真的可以使用一些新的想法。

Public CHECK_INTERVAL_IN_MILLISECONDS As Integer = 1000 '1 second

''' <summary>
''' Initializes the timer that will work as a check interval
''' </summary>
Private Sub initializeTimer()
    _timer = New Timer(CHECK_INTERVAL_IN_MILLISECONDS)
    AddHandler _timer.Elapsed, New ElapsedEventHandler(AddressOf checkScheduledItems)
    _timer.Enabled = True
End Sub 

''' <summary>
''' The items are timed at HH:mm and executed every N minutes.
''' For example, I could make an item be scheduled at 01:00 every 12*60 minutes and it would be executed at 1am and at 1pm every day.
''' </summary>  
Public Sub checkScheduledItems(ByVal timeMarginInMilliseconds As Double)

    'NOTE: timeMarginInMilliseconds = CHECK_INTERVAL_IN_MILLISECONDS

    Dim currentTime As Date = Now

    Dim exporterScheduleList = executionSchedule.getAllActiveItemsByPriority

    Dim hourSpan As Integer = 48

    'First deal with fixed dates:
    For Each executionScheduledItem As ExecutionSchedule In exporterScheduleList.Values

        If executionScheduledItem.active Then

            Dim baseExecTime As Date = executionScheduledItem.createBaseDate(currentTime)
            Dim execFrequencyInMinutes As Integer = executionScheduledItem.scheduled_frequency

            For minuteInterval As Integer = 0 To hourSpan * 60 Step execFrequencyInMinutes
                Dim execTime As Date = baseExecTime.AddMinutes(minuteInterval)
                Dim timeDiff = currentTime.Subtract(execTime).TotalMilliseconds
                If timeDiff >= 0 And timeDiff < timeMarginInMilliseconds Then

                    Dim newExecutionWaitlistItem As ExecutionWaitlist = New ExecutionWaitlist(executionScheduledItem)
                    newExecutionWaitlistItem.save()

                    Exit For 'stop checking the minute interval

                End If
            Next

        End If

    Next

End Sub

''' <summary>
''' Gets the scheduled_time (a string with format "HH:mm") and transforms it into a Date with -24h.
''' </summary>
Public Function createBaseDate(ByVal currentTime As Date) As Date
    Dim scheduled_time As String = Me.scheduled_time
    Dim scheduled_time_vector() As String = scheduled_time.Split(":")
    Dim baseExecTime = New Date(currentTime.Year, currentTime.Month, currentTime.Day, scheduled_time_vector(0), scheduled_time_vector(1), 0)
    baseExecTime.AddHours(-24)
    Return baseExecTime
End Function    

2 个答案:

答案 0 :(得分:1)

  

它是否真的是我在.NET代码中触发预定功能的唯一选择,正如所有其他帖子所暗示的那样?它看起来有点像拼凑而成。

您可以使用第三方调度程序库。 Quartz.NET非常好。

  

是否有跳过元素的概率?我的意思是:在执行时间等方面,我认为可能会以某种方式跳过执行时间检查的1秒间隔。

如果您每秒执行的任务花费的时间超过一秒,那么您将不会错过“ticks”(至少不使用System.Timers.Timer),但最终可能会创建大量线程,可以杀死你的应用程序性能,最终使内存不足。

  

有没有更好的方法来解决“分钟频率”部分?设置baseDate让我有点困惑......此外,它似乎只在小时设置为尽可能接近00:00时才起作用(例如:由于某种原因“每12小时18:00”将不会执行早上6点用当前代码)

不确定,但它表明这不是一个你想要解决的简单问题;你绝对应该使用现有的库,而不是重新发明轮子。

答案 1 :(得分:0)

如果任务计划程序不是一个选项,您可以创建一个每分钟执行一次的Windows服务应用程序。

Imports System.Timers

Private Timer As System.Threading.Timer = Nothing
Private ProcessRunning As Boolean = False

Protected Overrides Sub OnStart(ByVal args() As String)
        ProcessRunning = False
        Timer = New System.Threading.Timer(New Threading.TimerCallback(AddressOf Timer_Elapsed), Nothing, 0, 60000)
End Sub


Private Sub Timer_Elapsed(ByVal sender As Object)
        If Not ProcessRunning Then Execute()
End Sub

执行后,您可以检查触发代码的时间

Private Sub Execute()

    If DateTime.Now.ToString("hh:mm") = "12:00" Then

        'Call your function
        ProcessRunning = False
    End If

End Sub