【问题标题】:Terminate thread execution for 24 hours终止线程执行 24 小时
【发布时间】:2013-03-20 09:04:44
【问题描述】:

我的服务大部分都按应有的方式工作,但它应该每天只工作一次。

为了安排这个,我的老板建议我让工作线程睡到明天早上 7 点:

Thread.Sleep 调用直接从他编写的类似服务复制而来,该服务显然有效,但这总是引发 ArgumentOutOfRangeException - 返回的值为负数。

    Private Sub startExport()
#If Not Debug Then
            Thread.Sleep(1000 * 60 * 1)
#End If
        While runReportExport
            Try
                runExport()
            Catch ex As Exception
                el.WriteEntry("Error exporting data: {1}")
            Finally
                'sleep thread until tomorrow 7am
                Thread.Sleep(DateTime.Now.Subtract(Date.Today.AddDays(1).AddHours(7)))
            End Try
        End While
    End Sub

我对这一切是如何运作的感到相当困惑,所以如果有人能为我解释整个时间跨度的事情,我将不胜感激。

另一方面,我的朋友建议我以不同的方式管理线程执行。

他建议我这样做:

Private lastExecute As DateTime = DateTime.Now

Private Overrides Sub OnStart(ByVal args() As String)
    startService()
End Sub

Private Sub startService()
    Dim nextExecute = lastExecute.AddDays(1)
    If nextExecute >= DateTime.Now Then
        lastExecute = DateTime.Now

        tWorker = New Thread(AddressOf startExport)
        tWorker.IsBackground = True
        tWorker.Start()
    End If
End Sub

他说这将在启动时执行一次工作线程,而不是另一天再次执行。虽然这段代码可以正常工作,但它不会阻止服务循环一遍又一遍地执行工作线程(目前它在第一次运行完成后立即执行第二次)

就我个人而言,我对这两种方法都持开放态度,但我似乎都无法正常工作。

基本上,我最终需要的只是每天导出一次数据的服务。

我老板的 Thread.Sleep 选项似乎更简单,但我朋友的建议似乎更好。

谁能帮我解决这个问题(此时我不在乎我使用哪一个,只要它有效)?

【问题讨论】:

  • 是否需要将其作为服务而不是计划任务运行? stackoverflow.com/questions/6749026/…
  • 我不知道,只是有人告诉我把它写成服务,鉴于我目前的工作状态,我最好不要质疑订单
  • 也许您可以说您做了一些研究(表现出热情)并找到了一种更好、更强大的方法来按计划运行程序。
  • 正确的做法是使用计划任务
  • 所以在告诉我为此使用计划任务时,我是否应该推断在 Windows 服务中没有办法做到这一点?

标签: vb.net multithreading service windows-services


【解决方案1】:
 DateTime.Now.Subtract(Date.Today.AddDays(1).AddHours(7)))

您从当前时间中减去未来时间。这总是产生负值。卡布姆。

您需要将其反转,从未来时间中减去当前时间。为了清楚起见并避免在 DateTime.Now 上进行比赛:

Dim today = DateTime.Now
Dim tomorrow = today.Date.AddDays(1).AddHours(7)
Dim wait = tomorrow - today
Thread.Sleep(wait)

当服务停止时,您需要做一些有用的事情。最好使用 ManualResetEvent 完成,您将从其 WaitOne(wait) 方法中获得睡眠。顺便说一句,让一个线程休眠那么久而不做任何有用的事情是非常浪费的。请改用计时器。

【讨论】:

  • +1 用于发现错误,而不仅仅是推荐不同的方法。对于这么长的间隔,我可能也会建议使用计时器或计划任务,但你也修复了这个错误:)
  • 令人讨厌的是,我在发布这篇文章大约一个小时后发现了这个错误,因为我在经历了所有日期的事情后用一把细齿梳子做的事情可以这么说......但我懒得写我的自己的答案,基本上就是这里的答案,所以被接受了:)
【解决方案2】:

另一种方法,也是我使用的,每天运行一次特定任务是在计时器中设置任务。就我而言,我希望任务在每天早上 12:05 运行。因此,当我的程序启动时,我设置了计时器的初始间隔,以便第一个滴答声将在第二天凌晨 12:05 发生。之后,每天一次,在作为滴答声的一部分执行的代码结束时,我再次重置计时器间隔,以便下一个滴答声将在第二天凌晨 12:05 发生。

...

Timer1.Interval = MillisecondsToMidnight() + 300000 ' next tick 12:05:00 tomorrow

...

Private Function MillisecondsToMidnight() As Integer

    Dim ReturnValue As Integer
    Dim ts As TimeSpan

    Dim Tomorrow As DateTime = Today.AddDays(1)
    ts = Tomorrow.Subtract(Now)

    ReturnValue = ts.TotalMilliseconds()

    ts = Nothing
    Return ReturnValue

End Function

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多