由于OnStart()方法中的无限循环,Windows服务始终“正在启动”

时间:2011-01-05 17:50:54

标签: windows-services

我编写了一个Windows服务,定期执行一个SSIS包,将文档从Server A移动到Server B

问题是,为了做到这一点,我需要使用一个无限循环,它在服务启动时启动。

当然,我将此循环放入OnStart()方法中。不幸的是,该服务从未表示它已经启动,因为它从未达到此方法的终点......

以下是相关代码:

protected override void OnStart(string[] args)
{
    Application app = new Application();
    Package pkg = app.LoadFromDtsServer(@"MSDB\PullDoc", "Server", null);
    while (true)
    {
        DTSExecResult pkgResults = pkg.Execute();//Execute the package.
        EventLog.WriteEntry(pkgResults.ToString());
        Thread.Sleep(1000 * 60 * 5);//Sleep at least five minutes.
    }
}

我认为这是一个常见问题,因为大多数服务应该无限期运行。

关于如何让这项服务返回已经开始的任何想法?

谢谢!

4 个答案:

答案 0 :(得分:4)

您应该使用System.Threading.Timer而不是无限循环。

答案 1 :(得分:3)

您的服务应该在不同的线程上完成工作。 OnStartOnStop等方法可以从Windows服务控制管理器(SCM)处理命令到服务,SCM希望它们能够及时返回。

使用@SLaks建议的System.Threading.Timer实现了这一点:计时器事件将在.NET线程池的线程上执行。 OnStart方法只启用Timer,而OnStop方法禁用它(如果需要,OnPause和OnResume也可以这样做。)

答案 2 :(得分:2)

你没有正确地做到这一点,你永远不应该阻止一个函数返回,你应该使用一个新的线程。如建议的那样,您应该使用Timer对象。 这是一段代码片段,向您展示如何:

    private void OnElapsedTime(object source, ElapsedEventArgs e)
    {
         CopyAToB();
    }
    Timer timer = new Timer();
    protected override void OnStart(string[] args)
    {
        timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
        timer.Interval = 60000 * 5;
        timer.Enabled = true;
    }
    private void CopyAToB()
    {
        // do somethings
    }

答案 3 :(得分:1)

我建议您使用类似于建议的System.Threading.Timer,但这里是我将如何实现该功能的示例。

在这个例子中,我的函数每小时激活4次,它将快速验证它是否仍然从前一次调用运行,如果是,则跳过它,否则它将创建一个新线程并触发该函数。

Imports System.Threading

Public Class myService

  Private myThreadingTimer As System.Threading.Timer
  Private keepRunning As Boolean = False
  Private processing As Boolean = False

  Protected Overrides Sub OnStart(ByVal args() As String)
    Dim myTimerCallback As New TimerCallback(AddressOf OnTimedEvent)

    If YourCheckHere() Then
      keepRunning = True
      myThreadingTimer = New System.Threading.Timer(myTimerCallback, Nothing, 1000, 1000)
    Else
      'What you want to do here
    End If
  End Sub

  Protected Overrides Sub OnStop()
    keepRunning = False
  End Sub

  Private Sub OnTimedEvent(ByVal state As Object)
    If Date.Now.Minute = 14 And Date.Now.Second = 31 Or Date.Now.Minute = 29 And Date.Now.Second = 31 _
    Or Date.Now.Minute = 44 And Date.Now.Second = 31 Or Date.Now.Minute = 59 And Date.Now.Second = 31 _
    Then
      'Make Sure Its Supposed To Still Be Running
      If keepRunning Then
        'Make Sure The Process Is Not Already Running
        If Not processing Then
          'Process is not currently running lets start it
          Dim myThread As New Thread(New ThreadStart(AddressOf myProcess))
          myThread.Start()
       End If
      End If
    End If
  End Sub

  Public Sub myProcess()
    Try
      ' Set the processing flag so the function does not run again until complete
      processing = True

      'Do whatever logic you need here

    Catch ex As Exception
      'Since You Can Not Use A MessageBox Do Logging Or Whatever You Need Here

    Finally
      processing = False
    End Try
  End Sub

End Class