Windows Service always "Starting" because of infinite loop in OnStart() method
I've written a Windows Service that periodically executes a SSIS package that moves documents from Server A
to Server B
.
The problem is that in order to do so, I need to use an infinite loop, which starts when the Service starts.
Naturally, I placed this loop into the OnStart()
method. Unfortunately, the service never signals that it has started, since it never reaches the end of this method...
Here is the relevant code:
protected override void OnStart(string[] args)
{
Application app = new Application();
Package pkg = app.LoadFromDtsServer(@"MSDB\PullD开发者_开发问答oc", "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.
}
}
I would imagine this is a common problem, given that most Services should be running indefinitely.
Any ideas on how to get this service to return that it has started?
Thanks!
You should use a System.Threading.Timer
instead of an infinite loop.
Your service should do its work on a different thread. The OnStart
, OnStop
etc methods are there to process commands to your service from the Windows Service Control Manager (SCM), and the SCM expects them to return promptly.
Using a System.Threading.Timer
as suggested by @SLaks achieves this: the timer events will be executed on a thread from the .NET Thread Pool. Your OnStart method just Enables the Timer, while the OnStop method disables it (OnPause and OnResume can do likewise if you want).
You are not doing this correctly, you should never block a function from returning and you should use a new Thread. As it was suggested, you should use a Timer
object.
Here is a code snippet to show you how:
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
}
I would recommend that you use a System.Threading.Timer like suggested but here is an example of how I would implement the functionality.
In this example I have the function fire 4 times an hour and it will quickly validate if its still running from the previous call and if so skip it otherwise it will create a new thread and fire off the function.
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
精彩评论