Service endings prematurly

gotnetdude

Active member
Joined
Jan 24, 2008
Messages
27
Programming Experience
10+
Service endings prematurely

I wrote a simple test windows service application (see code below) that makes a call to S2K DB through XSD. The problem I'm having is that when I start the service it successfully make the initial call to the database, but after that it does not iterate through the code on the 60 second intervals. If I remove the call to the S2K DB then it iterates through the code perfectly fine. I'm stumped. How do I fix this?

VB.NET:
Public Class FanacSyncService

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

       Const iTimer_Interval As Integer = 60000
        Dim oTimer As System.Threading.Timer

        Dim tDelegate As Threading.TimerCallback = AddressOf FanacSync
        oTimer = New System.Threading.Timer(tDelegate, Me, 0, iTimer_Interval)

    End Sub

 Public Sub FanacSync(ByVal sender As Object)

        System.IO.File.AppendAllText("\\sn9218\fanacdatabase\test.txt", "step1")


        Dim FanacProdLogDT As New FanacSync.ProdlogDataTable
        Dim FanacProdLogAdapter As New FanacSyncTableAdapters.ProdlogTableAdapter
        Dim FanacProdLogRecordCount As Integer


        Dim MaxFanacSyncTransactionDateTime As Date = #1/1/2007#

        FanacProdLogRecordCount = _
            FanacProdLogAdapter.FillGetProdLogByStartSerial _
                            (FanacProdLogDT, MaxFanacSyncTransactionDateTime)

        FanacProdLogDT.Dispose()
        FanacProdLogAdapter.Dispose()

End Class
 
Last edited:
I'm not entirely sure I understand your code, but I would probably have done something along the lines of...

VB.NET:
Sub mainLoop
  Do
    ' Call your function here
    Thread.Sleep(60000)
  Loop
End Sub

You then start mainLoop from the OnStart event, in it's own thread if you like, and then stop that thread in the onStop.

Hope this is of some help.

Jim.
 
Thanks for the post, it was helpful. I was able to get it to work using the following code, but have one further question regarding this issue. How I can verify that the thread was actually aborted? Initial I tried using Thread.CurrentThread.Abort() command in OnStop, but was getting an error everytime I tried to stop the service. Is the method I used the best way to handle stopping the thread?

VB.NET:
Protected Override Sub OnStart(ByVal args() as string)

    dim FanacSyncThread as new ThreadingThread(Address of FanacSync)
    FanacSyscThread.Start()

end sub

Public sub FanacSync(byval sender as object)

Do WhileTrue
     
    DB call goes here...

    Thread.CurrentThread.Sleep(60000)

Loop

End Sub

Protected Overrides Sub OnStop()

      'This worked
      dim FanacSyncThread as new ThreadingThread(Address of FanacSync)
      FanacSyscThread.Abort()

end sub
 
Wat.


Protected Overrides Sub OnStop()

'This worked
dim FanacSyncThread as new ThreadingThread(Address of FanacSync)
This isnt the same "FanacSyncThread " as the one in OnStart. You've just created a new delegate.
FanacSyscThread.Abort()

end sub

Make FanacSyncThread a global variable.

Also, calling About will cause an exception because the loop is still running. You need to stop the while loop. Again use a global variable. Try somethign like this.

private _fanacSyncThread as ThreadingThread
private _isRunning as Boolean = True

Protected Override Sub OnStart(ByVal args() as string)

_fanacSyncThread = new ThreadingThread(Address of FanacSync)
_fanacSyncThread.Start()

end sub

Public sub FanacSync(byval sender as object)

Do While _isRunning

DB call goes here...

Thread.CurrentThread.Sleep(60000)

Loop

End Sub

Protected Overrides Sub OnStop()

'This worked
_isRunning = False
_fanacSyncThread.Join()

end sub
 
When the service control manager sends a control code to a service, it waits for the handler function to return before sending additional control codes to other services. The control handler must return within 30 seconds or the SCM returns an error. If a service must do lengthy processing when the service is executing the control handler, it should create a secondary thread to perform the lengthy processing, and then return from the control handler. This prevents the service from tying up the control dispatcher and blocking other services from receiving control codes.
This mean you don't have 60 seconds in OnStop to return the call. You have to configure this differently to get a more immediate handler response.
 
RockSteady thanks for the input seems to have gotten me past my first stumbling block.

JohnH, I was trying to implement your recommend restructuring method, but I'm running into an execution failure with the following code. Any suggestions:



VB.NET:
Imports System.Threading
Public Class Service1

    Private _LongProcessThread As New Threading.Thread(AddressOf LongLoadProcess)
    Private _fanacSyncThread As New Threading.Thread(AddressOf FanacSync)
    Private _isRunning As Boolean = True

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

        _fanacSyncThread.Start()

    End Sub

    Protected Overrides Sub OnStop()

        _isRunning = False
        _fanacSyncThread.Join()
        _LongProcessThread.Join()

    End Sub

    Public Sub FanacSync(ByVal sender As Object)

        Do While _isRunning

            _LongProcessThread.Start()

            '_fanacSyncThread.Sleep(60000)
            Thread.CurrentThread.Sleep(60000)

        Loop

    End Sub

    Public Sub LongLoadProcess(ByVal sender As Object)

        'load processing goes here

    End Sub


End Class
 
As long as you are using a Timer, you must keep a reference to it. As with any managed object, a Timer is subject to garbage collection when there are no references to it. The fact that a Timer is still active does not prevent it from being collected.
VB.NET:
Private t As Threading.Timer
Private sync As New Threading.ManualResetEvent(True)

Protected Overrides Sub OnStart(ByVal args() As String)
    t = New Threading.Timer(AddressOf tcb, Nothing, 1000, 60000)
End Sub

Private Sub tcb(ByVal state As Object)
    sync.Reset()
    'do work
    sync.Set()
End Sub

Protected Overrides Sub OnStop()
    t.Dispose()
    sync.WaitOne(3000, False)
End Sub
The ManualResetEvent can be used as in this example to ensure a started timer event work load finishes before the service stops. A 3 seconds timeout set for the wait too.
 

Latest posts

Back
Top