vb.net 需要一个定时器在特定时间和每 5 分钟触发一次直到作业完成

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28441916/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 18:47:26  来源:igfitidea点击:

Need A Timer To Fire At Specific Time And Every 5 Minutes Until Job Complete

vb.nettimer

提问by Riples

I need help setting up a specific type of timer for my application. My scenario is this:

我需要帮助为我的应用程序设置特定类型的计时器。我的场景是这样的:

I want to run a timer at a specific time of day (say 4:00AM). That timer then executes a number of different events that each go off and grab data from a database and process it (using background workers). All the different events take different times to finish (could be 30 seconds, could be 5 minutes). I want to continuously enter the timer event every 5 minutes thereafter checking if all events have finished. If so, stop the timer and restart it again at 4:00AM the next morning and so on.

我想在一天中的特定时间(比如凌晨 4:00)运行一个计时器。然后,该计时器执行许多不同的事件,每个事件都会触发并从数据库中获取数据并对其进行处理(使用后台工作人员)。所有不同的事件需要不同的时间来完成(可能是 30 秒,可能是 5 分钟)。我想每 5 分钟连续输入一次计时器事件,然后检查是否所有事件都已完成。如果是这样,请停止计时器并在第二天早上 4:00 重新启动它,依此类推。

So the process would look like this:

所以这个过程看起来像这样:

04:00AM - Start Timer and initiate background workers
04:05AM - Check again to see if processes have completed (if so, stop timer)
04:10AM - Check again to see if processes have completed (if so, stop timer)
And so on....

04:00AM - 启动计时器并启动后台工作人员
04:05AM - 再次检查进程是否已完成(如果是,停止计时器)
04:10AM - 再次检查以查看进程是否已完成(如果是,停止计时器)
等等在....

I already have my background worker code that processes my database information. So I just need help setting up the timer.

我已经有了处理我的数据库信息的后台工作代码。所以我只需要帮助设置计时器。

So far I have the following in my Tickevent:

到目前为止,我的Tick活动中有以下内容:

Private Sub tmr_Maintenance_Tick(sender As Object, e As EventArgs) Handles tmr_Maintenance.Tick
    Dim CurrentTime As Date
    Dim CurrHour As Integer

        CurrentTime = DateTime.Now
        CurrHour = CurrentTime.Hour

        'Automatic Sales Import
        With My.Settings
            If CurrHour = 4 Then

                If Not .Maintenance_Ran Then
                    CreateLog("Maintenance Started")

                    If Not .Yesterdays_Sales_Imported Then
                        CreateLog("Importing Yesterday's Sales From Portal")
                        If Not YesterdaysSales_Worker.IsBusy Then YesterdaysSales_Worker.RunWorkerAsync()
                    End If

                    If Not .WTD_Sales_Imported Then
                        CreateLog("Importing Week To Date Sales From Portal")
                        If Not WeekToDateSales_Worker.IsBusy Then WeekToDateSales_Worker.RunWorkerAsync()
                    End If

                    If Not .LW_Sales_Imported Then
                        CreateLog("Importing Last Week Sales From Portal")
                        If Not LastWeekSales_Worker.IsBusy Then LastWeekSales_Worker.RunWorkerAsync()
                    End If

                    If .Yesterdays_Sales_Imported = True And .WTD_Sales_Imported = True And .LW_Sales_Imported = True Then
                        .Maintenance_Ran = True
                    End If
                End If
            Else
                .Maintenance_Ran = False
            End If
        End With

    My.Settings.Save()
End Sub

Any help appreciated thanks.

任何帮助表示感谢。

采纳答案by Idle_Mind

Here's a basic framework you can start from:

这是您可以从以下基础框架开始的:

Public Class Form1

    Private Enum MaintenanceState
        WaitingToStart
        Started
    End Enum

    Private Target As DateTime
    Private state As MaintenanceState = MaintenanceState.WaitingToStart
    Private MaintenanceTime As New TimeSpan(4, 0, 0) ' 4:00 am
    Private WaitingInterval As New TimeSpan(0, 5, 0) ' Five minutes

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Target = GetNextMaintenanceTarget(MaintenanceTime)
        tmr_Maintenance.Interval = 1000
        tmr_Maintenance.Start()
    End Sub

    Private Sub tmr_Maintenance_Tick(sender As Object, e As EventArgs) Handles tmr_Maintenance.Tick
        ' optionally display time remaining until next target
        Dim ts As TimeSpan = Target.Subtract(DateTime.Now)
        Label1.Text = ts.ToString("hh\:mm\:ss")

        ' see if we've hit the target
        If DateTime.Now >= Target Then
            tmr_Maintenance.Stop()

            Select Case state
                Case MaintenanceState.WaitingToStart

                    ' ... start all the jobs ...

                    state = MaintenanceState.Started
                    Target = DateTime.Now.Add(WaitingInterval)

                Case MaintenanceState.Started

                    ' ... check to see if the jobs are all done ...

                    If Not AllJobsCompleted Then
                        Target = DateTime.Now.Add(WaitingInterval)
                    Else
                        state = MaintenanceState.WaitingToStart
                        Target = GetNextMaintenanceTarget(MaintenanceTime)
                    End If

            End Select

            tmr_Maintenance.Start()
        End If
    End Sub

    Private Function GetNextMaintenanceTarget(ByVal time As TimeSpan) As DateTime
        Dim dt As DateTime = DateTime.Today.Add(time)
        If DateTime.Now > dt Then
            dt = dt.AddDays(1) ' already past target time for today, next start is tomorrow
        End If
        Return dt
    End Function

End Class

回答by CoderDennis

Instead of firing your timer every second and checking the current hour (which seems problematic anyway) why not calculate how many milliseconds until 4 am and set the timer to fire at that time?

与其每秒触发计时器并检查当前小时(无论如何这似乎有问题),为什么不计算凌晨 4 点之前的毫秒数并将计时器设置为在那个时间触发?

Dim timer = New Timer()
timer.Interval = MillisecondsUntilNextFourAm

...

Function MillisecondsUntilNextFourAm() As Integer
    Dim now = DateTime.Now()
    If now.Hour < 4 Then
        Return (TimeSpan.FromHours(4) - now.TimeOfDay).TotalMilliseconds
    Else
        Return (TimeSpan.FromHours(28) - now.TimeOfDay).TotalMilliseconds
    End If
End Function

You could do something similar if you then want the timer to fire again in 5 minutes. I would set the timer's AutoResetproperty to Falseand call Starteach time after setting the interval.

如果您希望计时器在 5 分钟内再次触发,您可以执行类似的操作。我会将计时器的AutoReset属性设置为FalseStart在设置间隔后每次调用。