Riferimento a .NET Framework
Classe ServiceBase

Aggiornamento: novembre 2007

Fornisce una classe base per un servizio che esisterà nel contesto di un'applicazione di servizio. È necessario derivare ServiceBase durante la creazione di una nuova classe di servizio.

Spazio dei nomi:  System.ServiceProcess
Assembly:  System.ServiceProcess (in System.ServiceProcess.dll)

Sintassi

Visual Basic - (Dichiarazione)
Public Class ServiceBase _
    Inherits Component
Visual Basic (Utilizzo)
Dim instance As ServiceBase
C#
public class ServiceBase : Component
Visual C++
public ref class ServiceBase : public Component
J#
public class ServiceBase extends Component
JScript
public class ServiceBase extends Component
Note

Derivare da ServiceBase quando si definisce la classe di servizio in un'applicazione di servizio. Ogni servizio utile esegue l'override dei metodi OnStart e OnStop. Per funzionalità aggiuntive, è possibile eseguire l'override di OnPause e OnContinue con un funzionamento specifico in risposta alle variazioni dello stato di servizio.

Il servizio è un eseguibile ad esecuzione prolungata che non supporta un'interfaccia utente e che potrebbe non essere avviato con l'account utente connesso. Per eseguire il servizio non è necessario che un utente sia connesso al computer.

In base all'impostazione predefinita, i servizi vengono eseguiti con l'account System, che non corrisponde all'account Administrator. Non è possibile modificare i privilegi dell'account System. In alternativa, è possibile utilizzare un oggetto ServiceProcessInstaller per specificare un account utente con il quale verrà eseguito il servizio.

Un eseguibile può contenere più servizi ma è necessario che contenga un oggetto ServiceInstaller separato per ciascuno di essi. L'istanza di ServiceInstaller registra il servizio nel sistema. Il programma di installazione, inoltre, associa ciascun servizio a un registro eventi che può essere utilizzato per registrare i comandi di servizio. La funzione main() nell'eseguibile definisce quali servizi è necessario eseguire. La directory di lavoro corrente del servizio è la directory di sistema e non quella in cui si trova l'eseguibile.

Quando si avvia un servizio, il sistema individua l'eseguibile ed esegue il metodo OnStart per tale servizio, contenuto all'interno dell'eseguibile. Eseguire un servizio, tuttavia, non significa avviare l'eseguibile. L'eseguibile carica solo il servizio. Al servizio è possibile accedere (ad esempio, per l'avvio e l'interruzione) mediante Gestione controllo servizi.

L'eseguibile chiama il costruttore della classe derivata ServiceBase la prima volta che si chiama il metodo Start sul servizio. Il metodo per la gestione dei comandi OnStart viene chiamato subito dopo l'esecuzione del costruttore. Poiché il costruttore non viene più eseguito dopo il primo caricamento del servizio, è necessario separare l'elaborazione eseguita dal costruttore da quella eseguita dal metodo OnStart . È necessario che tutte le risorse che possono essere rilasciate dal metodo OnStop siano create nel metodo OnStart . La creazione di risorse nel costruttore ne impedisce la creazione corretta se il servizio viene riavviato dopo che il metodo OnStop le ha rilasciate.

Gestione controllo servizi (SCM, Service Control Manager) fornisce un modo per interagire con il servizio. Il gestore SCM può essere utilizzato per passare comandi di avvio, interruzione, pausa o continuazione oppure comandi personalizzati nel servizio. Il gestore SCM utilizza i valori di CanStop e CanPauseAndContinue per determinare se il servizio accetta i comandi di avvio, pausa o continuazione. Tali comandi vengono attivati nei menu di scelta rapida di SCM solo se la corrispondente proprietà CanStop o CanPauseAndContinue è true nella classe di servizio. Se attivato, il comando viene passato al servizio e viene chiamato OnStop, OnPause o OnContinue. Se la proprietà CanStop, CanShutdown o CanPauseAndContinue è false, il corrispondente metodo per la gestione dei comandi (ad esempio OnStop ) non verrà elaborato, anche se il metodo è stato implementato.

È possibile utilizzare la classe ServiceController per eseguire in modo programmatico ciò che il gestore SCM effettua tramite un'interfaccia utente. È possibile automatizzare le attività disponibili nella console. Se CanStop, CanShutdown o CanPauseAndContinue è true ma non è stato implementato un corrispondente metodo per la gestione dei comandi (ad esempio OnStop), il sistema genera un'eccezione e ignora il comando.

Non è necessario implementare OnStart, OnStop o un altro metodo in ServiceBase. Comunque, il funzionamento del servizio è descritto nel OnStart, quindi occorrere almeno eseguire l'override di questo membro. La funzione main() del file eseguibile registra il servizio nel file eseguibile con il gestore SCM mediante la chiamata del metodo Run. La proprietà ServiceName dell'oggetto ServiceBase passata al metodo Run deve corrispondere alla proprietà ServiceName del programma di installazione di tale servizio.

Per installare servizi nel sistema, è possibile utilizzare InstallUtil.exe.

Nota:

Sebbene sia possibile specificare un log diverso dal log eventi delle applicazioni per ricevere la notifica delle chiamate ai servizi, tenere presente che le proprietà AutoLog e EventLog non possono scrivere in un log personalizzato. Se non si desidera utilizzare la registrazione automatica, impostare AutoLog su false.

Esempi

Nell'esempio seguente la semplice implementazione di un servizio viene derivata dalla classe ServiceBase. Il servizio gestisce vari comandi di servizio tra i quali Stop, Start, Pause, Continue e i comandi personalizzati.

Visual Basic
' Turn on logging to the event log.
#Const LOGEVENTS = True

Imports System
Imports System.IO
Imports System.Threading
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Diagnostics
Imports System.ServiceProcess
Imports System.Text
Imports Microsoft.Win32
Imports System.Runtime.InteropServices


' Define custom commands for the SimpleService.

Public Enum SimpleServiceCustomCommands
    StopWorker = 128
    RestartWorker
    CheckWorker
End Enum 'SimpleServiceCustomCommands
<StructLayout(LayoutKind.Sequential)> _
Public Structure SERVICE_STATUS
    Public serviceType As Integer
    Public currentState As Integer
    Public controlsAccepted As Integer
    Public win32ExitCode As Integer
    Public serviceSpecificExitCode As Integer
    Public checkPoint As Integer
    Public waitHint As Integer
End Structure 'SERVICE_STATUS


Public Enum State
    SERVICE_STOPPED = &H1
    SERVICE_START_PENDING = &H2
    SERVICE_STOP_PENDING = &H3
    SERVICE_RUNNING = &H4
    SERVICE_CONTINUE_PENDING = &H5
    SERVICE_PAUSE_PENDING = &H6
    SERVICE_PAUSED = &H7
End Enum 'State

' Define a simple service implementation.

Public Class SimpleService
    Inherits System.ServiceProcess.ServiceBase
    Private Shared userCount As Integer = 0
    Private Shared pause As New ManualResetEvent(False)

    Public Declare Auto Function SetServiceStatus Lib "ADVAPI32.DLL" Alias "SetServiceStatus" (ByVal hServiceStatus As IntPtr, ByRef lpServiceStatus As SERVICE_STATUS) As Boolean
    Private myServiceStatus As SERVICE_STATUS

    Private workerThread As Thread = Nothing

    Public Sub New()
        CanPauseAndContinue = True
        CanHandleSessionChangeEvent = True
        CanShutdown = True
        CanStop = True
        ServiceName = "Simple Service"
        System.Diagnostics.EventLog.WriteEntry("SimpleService", DateTime.Now.ToLongTimeString())

    End Sub 'New

    Shared Sub Main()
#If LOGEVENTS Then
        System.Diagnostics.EventLog.WriteEntry("SimpleService.Main", DateTime.Now.ToLongTimeString() + " - Service main method starting...")
#End If

        ' Load the service into memory.
        System.ServiceProcess.ServiceBase.Run(New SimpleService())

#If LOGEVENTS Then
        System.Diagnostics.EventLog.WriteEntry("SimpleService.Main", DateTime.Now.ToLongTimeString() + " - Service main method exiting...")
#End If

    End Sub 'Main



    ' Start the service.
    Protected Overrides Sub OnStart(ByVal args() As String)
        Dim handle As IntPtr = Me.ServiceHandle
        myServiceStatus.currentState = Fix(State.SERVICE_START_PENDING)
        SetServiceStatus(handle, myServiceStatus)

        ' Start a separate thread that does the actual work.
        If workerThread Is Nothing OrElse (workerThread.ThreadState And System.Threading.ThreadState.Unstarted Or System.Threading.ThreadState.Stopped) <> 0 Then
#If LOGEVENTS Then
            System.Diagnostics.EventLog.WriteEntry("SimpleService.OnStart", DateTime.Now.ToLongTimeString() + " - Starting the service worker thread.")
#End If

            workerThread = New Thread(New ThreadStart(AddressOf ServiceWorkerMethod))
            workerThread.Start()
        End If
#If LOGEVENTS Then
        If Not (workerThread Is Nothing) Then
            System.Diagnostics.EventLog.WriteEntry("SimpleService.OnStart", DateTime.Now.ToLongTimeString() + " - Worker thread state = " + workerThread.ThreadState.ToString())
        End If
#End If
        myServiceStatus.currentState = Fix(State.SERVICE_RUNNING)
        SetServiceStatus(handle, myServiceStatus)
        System.Diagnostics.EventLog.WriteEntry("SimpleService", "Starting SimpleService")

        ' Get arguments from the ImagePath string value for the service's registry 
        ' key (HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SimpleService).
        ' These arguments are not used by this sample, this code is only intended to
        ' demonstrate how to obtain the arguments.
        Dim imagePathArgs As String() = Environment.GetCommandLineArgs()
        If imagePathArgs.Length > 1 Then
            System.Diagnostics.EventLog.WriteEntry("SimpleService.ImagePath", "argument 1: " + imagePathArgs(1))
            If imagePathArgs.Length > 2 Then
                System.Diagnostics.EventLog.WriteEntry("SimpleService.ImagePath", "argument 2: " + imagePathArgs(2))
            End If
        End If ' Get values for arguments passed in from the Services control panel or
        ' by the ServiceController class Start(string[]) method.
        ' Note:  The arguments are not persisted by the control panel. You must
        ' open the properties for the service, set the arguments, then start the
        ' service. You may find this functionality useful when debugging a service.
        ' These arguments are not used by this sample, this code is only
        ' intended to demonstrate how to obtain the arguments.
        If args.Length > 1 Then
            System.Diagnostics.EventLog.WriteEntry("SimpleService.Arguments", args(0))
            If args.Length > 1 Then
                System.Diagnostics.EventLog.WriteEntry("SimpleService.Arguments", args(1))
            End If
        End If

    End Sub 'OnStart

    ' Stop this service.
    Protected Overrides Sub OnStop()
        ' New in .NET Framework version 2.0.
        Me.RequestAdditionalTime(4000)
        ' Signal the worker thread to exit.
        If Not (workerThread Is Nothing) AndAlso workerThread.IsAlive Then
#If LOGEVENTS Then
            System.Diagnostics.EventLog.WriteEntry("SimpleService.OnStop", DateTime.Now.ToLongTimeString() + " - Stopping the service worker thread.")
#End If
            pause.Reset()
            Thread.Sleep(5000)
            workerThread.Abort()
        End If
        If Not (workerThread Is Nothing) Then
#If LOGEVENTS Then
            System.Diagnostics.EventLog.WriteEntry("SimpleService.OnStop", DateTime.Now.ToLongTimeString() + " - OnStop Worker thread state = " + workerThread.ThreadState.ToString())
#End If
        End If
        ' Indicate a successful exit.
        Me.ExitCode = 0

    End Sub 'OnStop

    ' Pause the service.
    Protected Overrides Sub OnPause()
        ' Pause the worker thread.
        If Not (workerThread Is Nothing) AndAlso workerThread.IsAlive AndAlso (workerThread.ThreadState And System.Threading.ThreadState.Suspended Or System.Threading.ThreadState.SuspendRequested) = 0 Then
#If LOGEVENTS Then
            System.Diagnostics.EventLog.WriteEntry("SimpleService.OnPause", DateTime.Now.ToLongTimeString() + " - Pausing the service worker thread.")
#End If

            pause.Reset()
            Thread.Sleep(5000)
        End If

        If Not (workerThread Is Nothing) Then
#If LOGEVENTS Then
            System.Diagnostics.EventLog.WriteEntry("SimpleService.OnPause", DateTime.Now.ToLongTimeString() + " OnPause - Worker thread state = " + workerThread.ThreadState.ToString())
#End If
        End If

    End Sub 'OnPause

    Protected Overrides Sub OnShutdown()
#If LOGEVENTS Then
        System.Diagnostics.EventLog.WriteEntry("SimpleService.OnShutdown", DateTime.Now.ToLongTimeString() + " - Stopping the SimpleService.")
#End If

    End Sub 'OnShutdown

    ' Continue a paused service.
    Protected Overrides Sub OnContinue()

        ' Signal the worker thread to continue.
        If Not (workerThread Is Nothing) AndAlso (workerThread.ThreadState And System.Threading.ThreadState.Suspended Or System.Threading.ThreadState.SuspendRequested) <> 0 Then
#If LOGEVENTS Then
            System.Diagnostics.EventLog.WriteEntry("SimpleService.OnContinue", DateTime.Now.ToLongTimeString() + " - Resuming the service worker thread.")

#End If
            pause.Set()
        End If
#If LOGEVENTS Then
        If Not (workerThread Is Nothing) Then
            System.Diagnostics.EventLog.WriteEntry("SimpleService.OnContinue", DateTime.Now.ToLongTimeString() + " OnContinue - Worker thread state = " + workerThread.ThreadState.ToString())
#End If
        End If

    End Sub 'OnContinue

    ' Handle a custom command.
    Protected Overrides Sub OnCustomCommand(ByVal command As Integer)
#If LOGEVENTS Then
        System.Diagnostics.EventLog.WriteEntry("SimpleService.OnCustomCommand", DateTime.Now.ToLongTimeString() + " - Custom command received: " + command.ToString())
#End If

        ' If the custom command is recognized,
        ' signal the worker thread appropriately.
        Select Case command
            Case Fix(SimpleServiceCustomCommands.StopWorker)
                ' Signal the worker thread to terminate.
                ' For this custom command, the main service
                ' continues to run without a worker thread.
                pause.Reset()

            Case Fix(SimpleServiceCustomCommands.RestartWorker)

                ' Restart the worker thread if necessary.
                pause.Set()

            Case Fix(SimpleServiceCustomCommands.CheckWorker)
#If LOGEVENTS Then
                ' Log the current worker thread state.
                System.Diagnostics.EventLog.WriteEntry("SimpleService.OnCustomCommand", DateTime.Now.ToLongTimeString() + " OnCustomCommand - Worker thread state = " + workerThread.ThreadState.ToString())
#End If


            Case Else
#If LOGEVENTS Then
                System.Diagnostics.EventLog.WriteEntry("SimpleService.OnCustomCommand", DateTime.Now.ToLongTimeString())
#End If
        End Select

    End Sub 'OnCustomCommand

    ' Handle a session change notice
    Protected Overrides Sub OnSessionChange(ByVal changeDescription As SessionChangeDescription)
#If LOGEVENTS Then
        System.Diagnostics.EventLog.WriteEntry("SimpleService.OnSessionChange", DateTime.Now.ToLongTimeString() + " - Session change notice received: " + changeDescription.Reason.ToString() + "  Session ID: " + changeDescription.SessionId.ToString())
#End If

        Select Case changeDescription.Reason
            Case SessionChangeReason.SessionLogon
                userCount += 1
#If LOGEVENTS Then
                System.Diagnostics.EventLog.WriteEntry("SimpleService.OnSessionChange", DateTime.Now.ToLongTimeString() + " SessionLogon, total users: " + userCount.ToString())
#End If
            Case SessionChangeReason.SessionLogoff

                userCount -= 1
#If LOGEVENTS Then
                System.Diagnostics.EventLog.WriteEntry("SimpleService.OnSessionChange", DateTime.Now.ToLongTimeString() + " SessionLogoff, total users: " + userCount.ToString())
#End If
            Case SessionChangeReason.RemoteConnect
                userCount += 1
#If LOGEVENTS Then
                System.Diagnostics.EventLog.WriteEntry("SimpleService.OnSessionChange", DateTime.Now.ToLongTimeString() + " RemoteConnect, total users: " + userCount.ToString())
#End If
            Case SessionChangeReason.RemoteDisconnect
                userCount -= 1
#If LOGEVENTS Then
                System.Diagnostics.EventLog.WriteEntry("SimpleService.OnSessionChange", DateTime.Now.ToLongTimeString() + " RemoteDisconnect, total users: " + userCount.ToString())
#End If
            Case SessionChangeReason.SessionLock
#If LOGEVENTS Then
                System.Diagnostics.EventLog.WriteEntry("SimpleService.OnSessionChange", DateTime.Now.ToLongTimeString() + " SessionLock")
#End If
            Case SessionChangeReason.SessionUnlock
#If LOGEVENTS Then
                System.Diagnostics.EventLog.WriteEntry("SimpleService.OnSessionChange", DateTime.Now.ToLongTimeString() + " SessionUnlock")
#End If
            Case Else
        End Select

    End Sub 'OnSessionChange

    ' Define a simple method that runs as the worker thread for 
    ' the service.  
    Public Sub ServiceWorkerMethod()
#If LOGEVENTS Then
        System.Diagnostics.EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() + " - Starting the service worker thread.")
#End If

        Try
            Do
                ' Simulate 4 seconds of work.
                Thread.Sleep(4000)
                ' Block if the service is paused or is shutting down.
                pause.WaitOne()
#If LOGEVENTS Then
                System.Diagnostics.EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() + " - heartbeat cycle.")
#End If
            Loop While True
        Catch
            ' Another thread has signalled that this worker
            ' thread must terminate.  Typically, this occurs when
            ' the main service thread receives a service stop 
            ' command.
            ' Write a trace line indicating that the worker thread
            ' is exiting.  Notice that this simple thread does
            ' not have any local objects or data to clean up.
#If LOGEVENTS Then
            System.Diagnostics.EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() + " - Thread abort signaled.")
#End If
        End Try
#If LOGEVENTS Then

        System.Diagnostics.EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() + " - Exiting the service worker thread.")
#End If

    End Sub 'ServiceWorkerMethod 
End Class 'SimpleService
C#
// Turn on logging to the event log.
#define LOGEVENTS

using System;
using System.IO;
using System.Threading;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using Microsoft.Win32;
using System.Runtime.InteropServices;

namespace SimpleService
{
    // Define custom commands for the SimpleService.
    public enum SimpleServiceCustomCommands { StopWorker = 128, RestartWorker, CheckWorker };
    [StructLayout(LayoutKind.Sequential)]
    public struct SERVICE_STATUS
    {
        public int serviceType;
        public int currentState;
        public int controlsAccepted;
        public int win32ExitCode;
        public int serviceSpecificExitCode;
        public int checkPoint;
        public int waitHint;
    }

    public enum State
    {
        SERVICE_STOPPED = 0x00000001,
        SERVICE_START_PENDING = 0x00000002,
        SERVICE_STOP_PENDING = 0x00000003,
        SERVICE_RUNNING = 0x00000004,
        SERVICE_CONTINUE_PENDING = 0x00000005,
        SERVICE_PAUSE_PENDING = 0x00000006,
        SERVICE_PAUSED = 0x00000007,
    }

    // Define a simple service implementation.
    public class SimpleService : System.ServiceProcess.ServiceBase
    {
        private static int userCount = 0;
        private static ManualResetEvent pause = new ManualResetEvent(false);

        [DllImport("ADVAPI32.DLL", EntryPoint = "SetServiceStatus")]
        public static extern bool SetServiceStatus(
                        IntPtr hServiceStatus,
                        ref SERVICE_STATUS lpServiceStatus
                        );
        private SERVICE_STATUS myServiceStatus;

        private Thread workerThread = null;

        public SimpleService()
        {
            CanPauseAndContinue = true;
            CanHandleSessionChangeEvent = true;
            CanShutdown = true;
            CanStop = true;
            ServiceName = "Simple Service";
            EventLog.WriteEntry("SimpleService", DateTime.Now.ToLongTimeString());
        }

        static void Main()
        {
#if LOGEVENTS
            EventLog.WriteEntry("SimpleService.Main", DateTime.Now.ToLongTimeString() +
                " - Service main method starting...");
#endif

            // Load the service into memory.
            System.ServiceProcess.ServiceBase.Run(new SimpleService());

#if LOGEVENTS
            EventLog.WriteEntry("SimpleService.Main", DateTime.Now.ToLongTimeString() +
                " - Service main method exiting...");
#endif

        }


        // Start the service.
        protected override void OnStart(string[] args)
        {
            IntPtr handle = this.ServiceHandle;
            myServiceStatus.currentState = (int)State.SERVICE_START_PENDING;
            SetServiceStatus(handle, ref myServiceStatus);

            // Start a separate thread that does the actual work.

            if ((workerThread == null) ||
                ((workerThread.ThreadState &
                 (System.Threading.ThreadState.Unstarted | System.Threading.ThreadState.Stopped)) != 0))
            {
#if LOGEVENTS
                EventLog.WriteEntry("SimpleService.OnStart", DateTime.Now.ToLongTimeString() +
                    " - Starting the service worker thread.");
#endif

                workerThread = new Thread(new ThreadStart(ServiceWorkerMethod));
                workerThread.Start();
            }
#if LOGEVENTS
            if (workerThread != null)
            {
                EventLog.WriteEntry("SimpleService.OnStart", DateTime.Now.ToLongTimeString() +
                    " - Worker thread state = " +
                    workerThread.ThreadState.ToString());
            }
#endif
            myServiceStatus.currentState = (int)State.SERVICE_RUNNING;
            SetServiceStatus(handle, ref myServiceStatus);
            EventLog.WriteEntry("SimpleService", "Starting SimpleService");

            // Get arguments from the ImagePath string value for the service's registry 
            // key (HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SimpleService).
            // These arguments are not used by this sample, this code is only intended to
            // demonstrate how to obtain the arguments.
            string[] imagePathArgs = Environment.GetCommandLineArgs();
            if (imagePathArgs.Length > 1)
            {
                EventLog.WriteEntry("SimpleService.ImagePath", "argument 1: " + imagePathArgs[1]);
                if (imagePathArgs.Length > 2)
                    EventLog.WriteEntry("SimpleService.ImagePath", "argument 2: " + imagePathArgs[2]);
            }
            // Get values for arguments passed in from the Services control panel or
            // by the ServiceController class Start(string[]) method.
            // Note:  The arguments are not persisted by the control panel. You must
            // open the properties for the service, set the arguments, then start the
            // service. You may find this functionality useful when debugging a service.
            // These arguments are not used by this sample, this code is only
            // intended to demonstrate how to obtain the arguments.
            if (args.Length > 1)
            {
                EventLog.WriteEntry("SimpleService.Arguments", args[0]);
                if (args.Length > 1)
                    EventLog.WriteEntry("SimpleService.Arguments", args[1]);
            }

        }

        // Stop this service.
        protected override void OnStop()
        {
            // New in .NET Framework version 2.0.
            this.RequestAdditionalTime(4000);
            // Signal the worker thread to exit.
            if ((workerThread != null) && (workerThread.IsAlive))
            {
#if LOGEVENTS
                EventLog.WriteEntry("SimpleService.OnStop", DateTime.Now.ToLongTimeString() +
                    " - Stopping the service worker thread.");
#endif
                pause.Reset();
                Thread.Sleep(5000);
                workerThread.Abort();

            }
            if (workerThread != null)
            {
#if LOGEVENTS
                EventLog.WriteEntry("SimpleService.OnStop", DateTime.Now.ToLongTimeString() +
                    " - OnStop Worker thread state = " +
                    workerThread.ThreadState.ToString());
#endif
            }
            // Indicate a successful exit.
            this.ExitCode = 0;
        }

        // Pause the service.
        protected override void OnPause()
        {
            // Pause the worker thread.
            if ((workerThread != null) &&
                (workerThread.IsAlive) &&
                ((workerThread.ThreadState &
                 (System.Threading.ThreadState.Suspended | System.Threading.ThreadState.SuspendRequested)) == 0))
            {
#if LOGEVENTS
                EventLog.WriteEntry("SimpleService.OnPause", DateTime.Now.ToLongTimeString() +
                    " - Pausing the service worker thread.");
#endif

                pause.Reset();
                Thread.Sleep(5000);
            }

            if (workerThread != null)
            {
#if LOGEVENTS
                EventLog.WriteEntry("SimpleService.OnPause", DateTime.Now.ToLongTimeString() +
                    " OnPause - Worker thread state = " +
                    workerThread.ThreadState.ToString());
#endif
            }
        }
        protected override void OnShutdown()
        {
#if LOGEVENTS
            EventLog.WriteEntry("SimpleService.OnShutdown", DateTime.Now.ToLongTimeString() +
                " - Stopping the SimpleService.");
#endif
        }
        // Continue a paused service.
        protected override void OnContinue()
        {

            // Signal the worker thread to continue.
            if ((workerThread != null) &&
                ((workerThread.ThreadState &
                 (System.Threading.ThreadState.Suspended | System.Threading.ThreadState.SuspendRequested)) != 0))
            {
#if LOGEVENTS
                EventLog.WriteEntry("SimpleService.OnContinue", DateTime.Now.ToLongTimeString() +
                    " - Resuming the service worker thread.");

#endif
                pause.Set();

            }
#if LOGEVENTS
            if (workerThread != null)
            {
                EventLog.WriteEntry("SimpleService.OnContinue", DateTime.Now.ToLongTimeString() +
                    " OnContinue - Worker thread state = " +
                    workerThread.ThreadState.ToString());
#endif
            }
        }

        // Handle a custom command.
        protected override void OnCustomCommand(int command)
        {
#if LOGEVENTS
            EventLog.WriteEntry("SimpleService.OnCustomCommand", DateTime.Now.ToLongTimeString() +
                " - Custom command received: " +
                command.ToString());
#endif

            // If the custom command is recognized,
            // signal the worker thread appropriately.

            switch (command)
            {
                case (int)SimpleServiceCustomCommands.StopWorker:
                    // Signal the worker thread to terminate.
                    // For this custom command, the main service
                    // continues to run without a worker thread.
                    pause.Reset();
                    break;

                case (int)SimpleServiceCustomCommands.RestartWorker:

                    // Restart the worker thread if necessary.
                    pause.Set();
                    break;

                case (int)SimpleServiceCustomCommands.CheckWorker:
#if LOGEVENTS
                    // Log the current worker thread state.
                    EventLog.WriteEntry("SimpleService.OnCustomCommand", DateTime.Now.ToLongTimeString() +
                        " OnCustomCommand - Worker thread state = " +
                        workerThread.ThreadState.ToString());
#endif

                    break;

                default:
#if LOGEVENTS
                    EventLog.WriteEntry("SimpleService.OnCustomCommand",
                        DateTime.Now.ToLongTimeString());
#endif
                    break;
            }
        }
        // Handle a session change notice
        protected override void OnSessionChange(SessionChangeDescription changeDescription)
        {
#if LOGEVENTS
            EventLog.WriteEntry("SimpleService.OnSessionChange", DateTime.Now.ToLongTimeString() +
                " - Session change notice received: " +
                changeDescription.Reason.ToString() + "  Session ID: " +
                changeDescription.SessionId.ToString());
#endif

            switch (changeDescription.Reason)
            {
                case SessionChangeReason.SessionLogon:
                    userCount += 1;
#if LOGEVENTS
                    EventLog.WriteEntry("SimpleService.OnSessionChange",
                        DateTime.Now.ToLongTimeString() +
                        " SessionLogon, total users: " +
                        userCount.ToString());
#endif
                    break;
                case SessionChangeReason.SessionLogoff:

                    userCount -= 1;
#if LOGEVENTS
                    EventLog.WriteEntry("SimpleService.OnSessionChange",
                        DateTime.Now.ToLongTimeString() +
                        " SessionLogoff, total users: " +
                        userCount.ToString());
#endif
                    break;
                case SessionChangeReason.RemoteConnect:
                    userCount += 1;
#if LOGEVENTS
                    EventLog.WriteEntry("SimpleService.OnSessionChange",
                        DateTime.Now.ToLongTimeString() +
                        " RemoteConnect, total users: " +
                        userCount.ToString());
#endif
                    break;
                case SessionChangeReason.RemoteDisconnect:
                    userCount -= 1;
#if LOGEVENTS
                    EventLog.WriteEntry("SimpleService.OnSessionChange",
                        DateTime.Now.ToLongTimeString() +
                        " RemoteDisconnect, total users: " +
                        userCount.ToString());
#endif
                    break;
                case SessionChangeReason.SessionLock:
#if LOGEVENTS
                    EventLog.WriteEntry("SimpleService.OnSessionChange",
                        DateTime.Now.ToLongTimeString() +
                        " SessionLock");
#endif
                    break;
                case SessionChangeReason.SessionUnlock:
#if LOGEVENTS
                    EventLog.WriteEntry("SimpleService.OnSessionChange",
                        DateTime.Now.ToLongTimeString() +
                        " SessionUnlock");
#endif
                    break;
                default:
                    break;
            }
        }
        // Define a simple method that runs as the worker thread for 
        // the service.  
        public void ServiceWorkerMethod()
        {
#if LOGEVENTS
            EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() +
                " - Starting the service worker thread.");
#endif

            try
            {
                do
                {
                    // Simulate 4 seconds of work.
                    Thread.Sleep(4000);
                    // Block if the service is paused or is shutting down.
                    pause.WaitOne();
#if LOGEVENTS
                    EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() +
                        " - heartbeat cycle.");
#endif
                }
                while (true);
            }
            catch (ThreadAbortException)
            {
                // Another thread has signalled that this worker
                // thread must terminate.  Typically, this occurs when
                // the main service thread receives a service stop 
                // command.

                // Write a trace line indicating that the worker thread
                // is exiting.  Notice that this simple thread does
                // not have any local objects or data to clean up.
#if LOGEVENTS
                EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() +
                    " - Thread abort signaled.");
#endif
            }
#if LOGEVENTS

            EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() +
                " - Exiting the service worker thread.");
#endif

        }
    }
}
Gerarchia di ereditarietà

System..::.Object
  System..::.MarshalByRefObject
    System.ComponentModel..::.Component
      System.ServiceProcess..::.ServiceBase
Codice thread safe

Qualsiasi membro static (Shared in Visual Basic) pubblico di questo tipo è thread-safe. I membri di istanza non sono garantiti come thread-safe.
Piattaforme

Windows Vista, Windows XP SP2, Windows XP Media Center Edition, Windows XP Professional x64 Edition , Windows XP Starter Edition, Windows Server 2003, Windows Server 2000 SP4, Windows Millennium Edition, Windows 98

.NET Framework e .NET Compact Framework non supportano tutte le versioni di ciascuna piattaforma. Per un elenco delle versioni supportate, vedere Requisiti di sistema di .NET Framework.

Informazioni sulla versione

.NET Framework

Supportato in: 3.5, 3.0, 2.0, 1.1, 1.0
Vedere anche

Riferimenti

Tag :


Page view tracker