Avatar billede yezper Nybegynder
22. april 2006 - 19:17 Der er 6 kommentarer og
1 løsning

Windows Service

Jeg har lavet en testservice med følgende elementer:

Service1.vb
    Protected Overrides Sub OnStart(ByVal args() As String)
        ' Add code here to start your service. This method should set things
        ' in motion so your service can do its work.
        Timer1.Enabled = True
        IO.File.Create("C:\TEMP\Test\_startup.txt")
    End Sub

    Protected Overrides Sub OnStop()
        ' Add code here to perform any tear-down necessary to stop your service.
        Timer1.Enabled = False
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        IO.File.Create("C:\TEMP\Test\" & Guid.NewGuid.ToString & ".txt")
    End Sub


Der er inkluderet en Project Installer, og servicen installeres med InstallUtil Service1.exe

Det virker ikke, som om Timer1 ticker - når servicen startes, oprettes der rigtigt nok en tekstfil - men ikke, hver gang Timer1 skulle gøre det.

Nogen som har forslag til, hvad der kan være galt?
Avatar billede bernhof Nybegynder
23. april 2006 - 22:47 #1
Mener ikke du kan benytte en System.Windows.Forms timer i en Windows Service, da man som regel kører i et fuldkommen multi-threaded miljø, når man arbejder med services. Desuden har jeg hørt, at der kan være problemer med System.Timers.Timer i .NET framework 1.1 (ved ikke om det er rettet i 2.0), så jeg vil i stedet anbefale at du benytter System.Threading.Timer, som netop er beregnet til brug i et multi-threaded miljø.

Læs mere om den her: http://msdn2.microsoft.com/en-us/library/system.threading.timer.aspx
Avatar billede tuxic Nybegynder
24. april 2006 - 11:20 #2
Enig i bernhofs betragtning. yezper: Har du husket at lave en delegat til Timer1_Tick?
Avatar billede yezper Nybegynder
24. april 2006 - 19:33 #3
Hvordan får man det inkorporeret i en service med udgangspunkt i den kode jeg har skrevet?
Man kan ikke tilføje en System.Threading.Timer i design view, så vidt jeg kan se.
Avatar billede bernhof Nybegynder
26. april 2006 - 15:06 #4
Fjern din nuværende timer og lav en member variabel istedet:


  Public Class Service1
    Inherits System.ServiceProcess.ServiceBase

    'Din nye timer:
    Private mTimer As New System.Threading.Timer


Lav desuden en egenskab igennem hvilken du kan tilgå din nye timer på thread-safe vis:


    Private ReadOnly Property Timer As System.Threading.Timer
      Get
        SyncLock mTimer
          Return mTimer
        End SyncLock
      End Get
    End Property


Med SyncLock sikrer du, at timeren ikke tilgås samtidig fra flere forskellige tråde, og derved forårsager en fejl.

Når du skal starte/stoppe din timer kalder du Timer.Change(...) (dvs. du tilgår din timer igennem Property'en) - Læs i det link jeg lagde tidligere, hvordan du bruger Change-metoden korrekt.
Avatar billede bernhof Nybegynder
26. april 2006 - 15:16 #5
Eller nærmere- kig her: http://msdn2.microsoft.com/en-us/library/yz1c7148.aspx

Manglede forresten lige noget (skriver bare ud fra hukommelsen, har ikke lige noget Visual Studio jeg kan teste i :) - nemlig en callback sub:


  Private Sub OnTimerCallback(ByVal state As Object)
    'Skriv her, hvad der skal ske når timeren 'tikker'
  End Sub


Callback sub'en SKAL angives i System.Threading.Timer constructoren, så nedenstående er altså en rettelse til den member variabel jeg skrev tidligere:


  Private mTimer As New System.Threading.Timer(AddressOf OnTimerCallback)


Du kan også i samme linie angive de samme parametre som Change metoden tager imod, hvis du gerne vil sætte timeren igang med det samme. Læs her: http://msdn2.microsoft.com/en-us/library/system.threading.timer.timer(VS.80).aspx
Avatar billede yezper Nybegynder
26. april 2006 - 17:51 #6
Tak for det, det virker perfekt. Læg et svar, så får du dine point ;o)
Den endelige testkode, som virker ser således ud:

Imports System.IO

Public Class CAS1
    Inherits System.ServiceProcess.ServiceBase

    Private mTimer As New System.Threading.Timer(AddressOf OnTimerCallback)

    Private ReadOnly Property MyTimer() As System.Threading.Timer
        Get
            SyncLock mTimer
                Return mTimer
            End SyncLock
        End Get
    End Property

    Private Sub OnTimerCallback(ByVal state As Object)
        'Skriv her, hvad der skal ske når timeren 'tikker'
        IO.File.Create("C:\TEMP\Test\" & Guid.NewGuid.ToString & ".txt")
    End Sub

    Protected Overrides Sub OnStart(ByVal args() As String)
        ' Add code here to start your service. This method should set things
        ' in motion so your service can do its work.

        IO.File.Create("C:\TEMP\Test\_" & Guid.NewGuid.ToString)
        MyTimer.Change(1000, 10000)
    End Sub

    Protected Overrides Sub OnStop()
        ' Add code here to perform any tear-down necessary to stop your service.
        'Timer1.Enabled = False
    End Sub
End Class
Avatar billede bernhof Nybegynder
27. april 2006 - 00:24 #7
Ser fint ud :)

Svar.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester



IT-JOB