Служба Windows всегда "запускается" из-за бесконечного цикла в методе OnStart () - PullRequest
2 голосов
/ 05 января 2011

Я написал службу 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 ]

4 голосов
/ 05 января 2011

Вы должны использовать System.Threading.Timer вместо бесконечного цикла.

3 голосов
/ 05 января 2011

Ваш сервис должен выполнять свою работу в другом потоке. Методы OnStart, OnStop и т.д. предназначены для обработки команд для вашей службы из диспетчера управления службами Windows (SCM), и SCM ожидает, что они будут возвращаться быстро.

Использование System.Threading.Timer в соответствии с предложением @SLaks позволяет добиться этого: события таймера будут выполняться в потоке из пула потоков .NET. Ваш метод OnStart просто включает таймер, а метод OnStop отключает его (OnPause и OnResume могут делать то же самое, если хотите).

2 голосов
/ 05 января 2011

Вы делаете это неправильно, вы никогда не должны блокировать возврат функции и должны использовать новый поток. Как было предложено, вы должны использовать объект 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
    }
1 голос
/ 06 января 2011

Я бы порекомендовал вам использовать 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...