Windows service - what happens if the code takes longer to execute than the interval allows if a Tim

H

hazz

What happens if I set the timer interval for a period that is less than the
time it will take to process the loop below? Right now my application is
returning just a few items in an arraylist to process but the process should
scale to 100 or even 1000 loops. If the functions contained within the loop,
some of which go out to web services, take an indeterminate amount of time,
how do I design my windows service so that if the code takes longer than the
interval, no funny things will happen? Thank you. -hazz

Public Class Service1
Inherits System.ServiceProcess.ServiceBase

Protected Overrides Sub OnStart(ByVal args() As String)
Timer1.Interval =
System.Configuration.ConfigurationSettings.AppSettings("Interval")
Timer1.Enabled = True
End Sub

Private Sub Timer1_Elapsed(ByVal sender As System.Object,
ByVal e As System.Timers.ElapsedEventArgs)
Handles Timer1.Elapsed
dim obj as New ControllerClass
For i = 1 to 100
obj.hydrate_business_objects()
obj.Do_100_millisecond_Function()
obj.Do_2_to_5_second_Function()
obj.PerformBusinessRules()
obj.UpdateDatabase()
Next
End Sub
End Class
 
C

Chris Dunaway

Generally speaking, in your Timer_Elapsed routine you should disable
the timer and then at the end of the routine re-enable it:

Public Sub Timer1_Elapsed(...)
Timer1.Enabled = False

'Processing Code here

Timer1.Enabled = True
End Sub

Or, when you enter the Timer_Elapsed routine, set a global boolean
switch to indicate that you are currently processing. Check that
switch when you execute:

If Not boolProcessing Then
boolProcessing = True

' Code to process here

boolProcessing = False
Endif
 
G

Guest

use a seperate worker thread to do the actual work. look up MSDN on threading
and thread pooling.
 
K

Ken Dopierala Jr.

Hi Hazz,

The easiest way could be to make Timer1.Disabled the first line of your
Elapsed event and Timer1.Enabled the last line. That way you are pausing
the Timer and it won't cause an event while processing. That should work
for the code you showed because they all appear to be blocking calls. If
you are spinning things on another thread then the easiest way is would
probably be to disable the timer when you start the process and also create
a delegate that you pass. When your processing is done have the last
process call that delegate to restart the timer. You may also want to throw
in a Application.DoEvents() to give Windows a chance to update the UI and
what not if your calls are coming in that fast. Good luck! Ken.
 
H

hazz

thanks for the great ideas and explanations Ken.
I am beginnning to see that putting in some traces to see what is happening,
along with time stamps, is a good idea.

thanks again,
-hazz
 
H

hazz

great idea Chris!
that totally makes sense. any elapsed time set for the timer is delayed by
the amount of time that the processing takes.
If i set the elapsed time for 20 minutes and the processing code takes +/-10
minutes, then the timer would not effectively go off every 20 minutes but
rather every +/- 30 minutes. Is that the idea?
thanks,
-hazz
 
H

hazz

So if i had something like this, where would I put my processing code? Still
in the Timer1.Elapsed code like the following?

'class level thread
Protected m_Thread as Thread

Protected Overrides Sub OnStart(ByVal args() As String)

Dim ts as new ThreadStart(AddressOf Execute )
m_Thread = new Thread( ts )
m_Thread.Start()
base.OnStart( args )

End Sub


private sub Execute()
Timer1.Interval =
System.Configuration.ConfigurationSettings.AppSettings("Interval")
Timer1.Enabled = True
End Sub

Private Sub Timer1_Elapsed(ByVal sender As System.Object,
ByVal e As System.Timers.ElapsedEventArgs)
Handles Timer1.Elapsed
dim obj as New ControllerClass
For i = 1 to 100
obj.hydrate_business_objects()
obj.Do_100_millisecond_Function()
obj.Do_2_to_5_second_Function()
obj.PerformBusinessRules()
obj.UpdateDatabase()
Next
End Sub
 
P

Phill. W

Chris Dunaway said:
Generally speaking, in your Timer_Elapsed routine you should disable
the timer and then at the end of the routine re-enable it:

Public Sub Timer1_Elapsed(...)
Timer1.Enabled = False
'Processing Code here
Timer1.Enabled = True
End Sub

Agreed, but I'm paranoid about an untrapped Exception somewhere
in my processing code that, given the above, would seem to kill my
Service stone dead (can you tell I've had this happen?).

Try this :

Private Sub Timer1_Elapsed(...)
Try
Timer1.Enabled = False

' Processing Code here

Catch ex as Exception
' Something nasty happened
' - log it to a file but /continue/ with ...

Finally
Timer1.Enabled = True

End If

End Sub

This way, with the /possible/ exception (sic) of a ThreadAbortException,
your Timer will *always* get enabled again, no matter what your
[managed] code gets up to.

HTH,
Phill W.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top