In un certo senso, SCM non può garantire che l'eccezione non verrà generata. Non controlla la manipolazione del servizio di un membro privato, naturalmente - ad es. se il codice di servizio aggiuntivo interessa _foo
.
Detto questo, si consideri il seguente scenario per vedere il motivo per cui la risposta alla tua domanda specifica è chiaramente no:
1) Costruisci il tuo servizio con le seguenti modifiche di dimostrare:
public partial class MyService : ServiceBase
{
private Object _foo;
private const string _logName = "MyService Log.txt"; // to support added logging
public MyService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
// demonstrative logging
var threadId = Thread.CurrentThread.ManagedThreadId;
using (var log = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + _logName, true))
{
log.WriteLine("{0}: In OnStart(string[]) on thread ID {1}. Sleeping for 10 seconds...", DateTime.Now, threadId);
}
// Sleep before initializing _foo to allow calling OnStop before OnStart completes unless the SCM synchronizes calls to the methods.
Thread.Sleep(10000);
_foo = new Object();
}
protected override void OnStop()
{
// demonstrative logging added
var threadId = Thread.CurrentThread.ManagedThreadId;
using (var log = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + _logName, true))
{
log.WriteLine("{0}: In OnStop() on thread ID {1}.", DateTime.Now, threadId);
}
if (_foo == null)
{
// demonstrative logging added
using (var log = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + _logName, true))
{
log.WriteLine("{0}: _foo == null", DateTime.Now);
}
throw new Exception("Assignment not visible"); // Can this happen?
}
_foo = null;
}
}
2) Apri una shell di comandi.
3) Aprire un'altra shell di comandi.
4) Nella prima shell di comando, installare il servizio (con sc create
) se non lo si è già fatto e avviarlo (con net start
). Si dovrebbe vedere:
Il servizio MyService sta iniziando .....
I puntini di trascinamento dovrebbe essere aggiunto uno per uno come l'SCM attende attraverso i 10 secondi di dormire per avviare il servizio.
5) Nella seconda shell di comando, provare a interrompere il servizio (con net stop
) prima che siano trascorsi 10 secondi. Dovresti vedere:
Il servizio è in corso o in arresto. Per favore riprova più tardi.
Quindi, l'avvio di un servizio è chiaramente un'operazione di blocco che deve essere completata prima che il servizio possa essere interrotto.
6) Controllare la prima shell di comando dopo che sono trascorsi 10 secondi. Si dovrebbe vedere: servizio
La MyService è stato avviato con successo.
7) Ritornare alla seconda shell di comando e provare a interrompere nuovamente il servizio. Dovresti vedere:
Il servizio MyService è in fase di arresto.
Il servizio MyService è stato arrestato correttamente.
8) il registro risultante - per esempio:
10/22/2013 7:28:55 AM: In OnStart (stringa []) su ID filo 4. dormitorio per 10 secondi ...
10/22/2013 7:29:17 AM: In OnStop() sul thread ID 5.
Avvio e arresto del servizio in modo rapido è più facile con due gusci di comando che penso; ma l'esempio funziona in modo simile anche con una shell di comando.
Infine, si potrebbe trovare Mitchell Taylor (CoolDadTx) 's risposta a a similar question in MSDN forums interessante come ho fatto io:
Il modello di threading utilizzato dal SCM non è documentato formalmente per quanto ne so. Ciò che è noto è che ogni servizio viene chiamato sul proprio thread. Tuttavia, SCM potrebbe o non potrebbe utilizzare un pool di thread per riutilizzare un thread tra i servizi. Quando viene chiamato un servizio (start, stop, comandi personalizzati, ecc.) È previsto che esegua il proprio compito e ritorni rapidamente. C'è un forte limite per quanto tempo ci vuole. Qualcosa di più di un rapido ritorno richiede che tu spinga la richiesta su un thread secondario per l'elaborazione. Lo SCM stesso viene eseguito su un thread separato, pertanto se un servizio richiede troppo tempo per rispondere, SCM lo vede bloccato. Questo è discusso qui: http://msdn.microsoft.com/en-us/library/ms684264(VS.85).aspx
UPDATE:
nota particolare l'articolo Service State Transitions MSDN cui l'articolo che Mitchell Taylor cita pubblicitari. Contiene un diagramma di stato che in modo piuttosto chiaro, &, documenta in modo autorevole le transizioni dello stato del servizio definite e si allinea con ciò che ho delineato sopra. Spiega anche in relazione al diagramma di stato come l'SCM non trasmetta a volte richieste di controllo di servizio per assicurare solo transizioni di stato definite.
Sono interessato a quali sono le garanzie. Non ho mai visto qualcosa come il tuo esempio che causa un problema; tuttavia, so che acquisire risorse legate all'identità del thread (nel nostro caso un mutex) ha causato problemi alla mia squadra in passato. –
Ho già fatto la stessa domanda. Lo scaverò. – spender
Qui (contrassegnato come duplicato): [Calling ServiceBase.OnStart e OnStop ... stessa istanza?] (Http: // StackOverflow.it/questions/10799937/calling-servicebase-onstart-and-onstop-same-instance) – spender