System.Threading.Timer does not tick

K

KnighT

I have a .net service that runs a System.Threading.Timer. The delegate
points to the function that the service should execute when the timer
elapses. Problem: The timer is not ticking.

I have never used this timer. I used the documentation from Microsoft
as a guide, but I cannot get this timer to work.

Protected Overrides Sub OnStart(ByVal args() As String)
Dim myTimer As New TimerState()

' Create the delegate that invokes methods for the timer.
Dim timerDelegate As New TimerCallback(AddressOf
checkDatabases)

' Create a timer that waits 0 seconds, then invokes every 60
seconds.
Dim timer As New Timer(timerDelegate, myTimer, 10000, 60000)

log.write("Service started ")

End Sub

The log.write("Service....") executes properly. Why is the timer not
working ?
 
L

lord.zoltar

' Create a timer that waits 0 seconds, then invokes every 60
seconds.
Dim timer As New Timer(timerDelegate, myTimer, 10000, 60000)

I've never created a timer this way. I usally start it explicitly
myTimer.start()
 
S

Stephany Young

And as soon as the log.write("Service started ") the OnStart event handler
ends and your timer ceases to exist!!!!!!!!!

Because ... you have declared as local to the event handler!

Move it (and your state object) to class scope or higher and you should be
in business.

Private m_timer As Timer = Nothing
Private m_myTimer As New TimerState

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

m_timer = New Timer(AddressOf checkDatabases, m_myTimer, 10000, 60000)

log.write("Service started ")

End Sub

Note also that, in VB.NET, you don't have to instantiate a delegate for the
TimerCallback. You can use AddressOf <method> directly.

Now for an anomily. Your comment says 'Create a timer that waits 0 seconds,
then invokes every 60 seconds.' but the duetime value specified in the
constructor is 10000 which indicates 10 seconds. As writ, the Timer will
'fire' after 10 seconds and then every 60 seconds after that.
 
K

KnighT

Stephany said:
And as soon as the log.write("Service started ") the OnStart event handler
ends and your timer ceases to exist!!!!!!!!!

Because ... you have declared as local to the event handler!

Move it (and your state object) to class scope or higher and you should be
in business.

Private m_timer As Timer = Nothing
Private m_myTimer As New TimerState

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

m_timer = New Timer(AddressOf checkDatabases, m_myTimer, 10000, 60000)

log.write("Service started ")

End Sub

Note also that, in VB.NET, you don't have to instantiate a delegate for the
TimerCallback. You can use AddressOf <method> directly.

Now for an anomily. Your comment says 'Create a timer that waits 0 seconds,
then invokes every 60 seconds.' but the duetime value specified in the
constructor is 10000 which indicates 10 seconds. As writ, the Timer will
'fire' after 10 seconds and then every 60 seconds after that.

Thank you Stephany, I will give that a try. That makes sense and
hopefully is the solution I am looking for. I was just playing around
with the due time and did not change the comment.
 
K

KnighT

KnighT said:
Thank you Stephany, I will give that a try. That makes sense and
hopefully is the solution I am looking for. I was just playing around
with the due time and did not change the comment.

This timer never works. I created a simple windows form to test the
timer and that ticks. The timer in my service never does what it is
supposed to do.

Even if the scope from my first post was incorrect, then it should
still call the delegate and execute the method checkDatabases AT LEAST
ONCE during the onStart(). But it never calls the delegate. WHY ?????
Source code is supposed to do it's job.
 
K

KnighT

KnighT said:
This timer never works. I created a simple windows form to test the
timer and that ticks. The timer in my service never does what it is
supposed to do.

Even if the scope from my first post was incorrect, then it should
still call the delegate and execute the method checkDatabases AT LEAST
ONCE during the onStart(). But it never calls the delegate. WHY ?????
Source code is supposed to do it's job.

Ok - I have now found part of the problem. The method call to
checkDatabases is not calling. So, I commented out all of the code in
the method and placed a simple log.write(). This wrote a line to the
log at every tick. When I uncomment the code, the timer never calls
the method.

Are there restrictions or limitations to the code you are allowed to
put into this delegate ? This just really makes no sense. Something
in the function must be stopping the method call. Services suck.
 
C

Chris Dunaway

KnighT said:
Ok - I have now found part of the problem. The method call to
checkDatabases is not calling. So, I commented out all of the code in
the method and placed a simple log.write(). This wrote a line to the
log at every tick. When I uncomment the code, the timer never calls
the method.

That makes no sense at all. Do you have exception handling in that
method? Perhaps it is throwing an exception. Check the Application
logs to see if it logged an exception or use try/catch to see if an
exception is occurring.
 
P

Phill W.

KnighT said:
Ok - I have now found part of the problem. The method call to
checkDatabases is not calling. So, I commented out all of the code in
the method and placed a simple log.write(). This wrote a line to the
log at every tick. When I uncomment the code, the timer never calls
the method.

If, for any reason, the JIT compiler can't load your timer method
(missing Assemblies or methods at runtime), the timer code simply isn't
called - and there's no log of the failure anywhere that I can find!

This is one reason I /don't/ use a Timer to drive a Service, only to
start it, as in:

Sub OnStart()
' Use the timer to side-step the call-and-return stack, to keep
' the Service Control Manager happy
tmrGo.Start()
End Sub

Sub tmrGo_Elapsed/Tick/whatever
' Kill the timer, which we don't need any more
tmrGo.Stop()

' Run the main process
Me.Run()

End Sub

Sub Run()
Do While Not ShutDownRequested()
Try

DoWork()

Catch ex As Exception

LogError( ex.ToString() )

End Try

For i As Integer = 1 to 30
If ShutDownRequested() Then Exit For
System.Threading.Thread.Sleep( 1000 )
Next
Loop

End Sub


Are you sure
 
K

KnighT

Phill said:
If, for any reason, the JIT compiler can't load your timer method
(missing Assemblies or methods at runtime), the timer code simply isn't
called - and there's no log of the failure anywhere that I can find!

This is one reason I /don't/ use a Timer to drive a Service, only to
start it, as in:

Sub OnStart()
' Use the timer to side-step the call-and-return stack, to keep
' the Service Control Manager happy
tmrGo.Start()
End Sub

Sub tmrGo_Elapsed/Tick/whatever
' Kill the timer, which we don't need any more
tmrGo.Stop()

' Run the main process
Me.Run()

End Sub

Sub Run()
Do While Not ShutDownRequested()
Try

DoWork()

Catch ex As Exception

LogError( ex.ToString() )

End Try

For i As Integer = 1 to 30
If ShutDownRequested() Then Exit For
System.Threading.Thread.Sleep( 1000 )
Next
Loop

End Sub


Are you sure

Well I finally figured it out....almost. The problem was that I
thought that the .exe file that .net compiled was self dependant. So I
never put any of the .dll files that I referenced in the project.

The thing that was really throwing me off was the lack of exception
being thrown. But I was able to see that it stopped executing the
source code at the declarations (Without throwing an exception). It
would just stop. After putting in the .dll files it went through the
entire method.

The second problem was correctly pointed out from the help of you guys.
This was instantiating the timer constructor in the OnStart() method.
The timer would tick once, sometimes twice, and rarely more than 4 or 5
times, then just stop.

So I put this timer in onStart(): Dim timer As New
Timer(timerDelegate, myTimer, 10000, 0)

which calls this method:

Sub startMainTimer(ByVal state As Object)
' Create a timer that waits one second, then invokes every 60
seconds.
log.write("Start main timer")
Dim timer As New Timer(AddressOf checkDatabases, myTimer,
10000, 60000)

' Keep a handle to the timer
myTimer.tmr = timer

While (Not myTimer.tmr Is Nothing)

End While

End Sub

So now my timer is ticking every minute and it is properly executing
the source code in the checkDatabases() method.

New problem: lots of errors from that method, which is uploading
databases. Which is strange because I have form that is doing the
exact same thing as the service and it works properly.

Anyways, thanks for your help. I received some very good advice that
helped alot.
 

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