In einer Hinsicht kann der SCM nicht garantieren, dass die von Ihnen umrissene Ausnahme nicht ausgelöst wird. Es steuert natürlich nicht die Manipulation eines privaten Mitglieds durch den Dienst - z. wenn sich zusätzlicher Servicecode auf _foo
auswirkt.
Having said dies, das folgende Szenario betrachten, um zu sehen, warum die Antwort auf Ihre Frage eindeutig nicht ist:
1) Bauen Sie Ihren Service mit folgenden Änderungen zu demonstrieren:
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) Öffnen Sie eine Befehlsshell.
3) Öffnen Sie eine weitere Befehlsshell.
4) Installieren Sie in der ersten Befehlsshell den Dienst (mit sc create
), falls noch nicht geschehen, und starten Sie ihn (mit net start
). Sie sollten sehen:
Der MyService Dienst starten wird .....
der nachlauf Punkte nacheinander hinzugefügt werden soll, wie die SCM der 10 Sekunden wartet durch Schlaf den Dienst zu starten.
5) Versuchen Sie in der zweiten Befehlsshell den Dienst (mit net stop
) zu stoppen, bevor 10 Sekunden verstreichen. Sie sollten folgendes sehen:
Der Dienst wird gestartet oder gestoppt. Bitte versuche es später erneut.
Das Starten eines Dienstes ist also eindeutig ein Blockiervorgang, der abgeschlossen werden muss, bevor der Dienst gestoppt werden kann.
6) Überprüfen Sie die erste Befehlsshell nach 10 Sekunden. Sie sollten Folgendes sehen:
Der MyService-Dienst wurde erfolgreich gestartet.
7) Kehren Sie zur zweiten Befehlsshell zurück und versuchen Sie, den Dienst erneut zu stoppen. Sie sollten Folgendes sehen:
Der MyService-Dienst wird angehalten.
Der MyService-Dienst wurde erfolgreich beendet.
8) Überprüfen des resultierenden log - zum Beispiel:
10/22/2013 7:28:55 AM: In OnStart (String []) auf Thread-ID 4 Schlafen für 10 Sekunden ...
10/22/2013 7:29:17 aM: In OnStop() auf Thread-ID 5.
Starten und den Dienst schnell zu stoppen ist einfacher mit zwei Befehlen-Shells ich denke; Das Beispiel funktioniert jedoch auch mit einer Befehlshülle.
Schließlich könnten Sie Mitchell Taylor (CoolDadTx) 's Antwort auf a similar question in MSDN forums interessant finden wie ich es tat:
Das Modell Einfädeln durch den SCM verwendet wird AFAIK nicht formal dokumentiert. Was bekannt ist, ist, dass jeder Dienst auf seinem eigenen Thread aufgerufen wird. Der SCM verwendet jedoch möglicherweise einen Thread-Pool, um einen Thread zwischen Diensten wiederzuverwenden. Wenn ein Dienst aufgerufen wird (Start, Stopp, benutzerdefinierte Befehle usw.), wird erwartet, dass er seine Aufgabe ausführt und schnell zurückkehrt. Es gibt eine starke Begrenzung, wie lange es dauern kann. Für mehr als eine schnelle Rückgabe müssen Sie die Anforderung zur Verarbeitung an einen sekundären Thread übergeben. Der SCM selbst läuft auf einem separaten Thread. Wenn ein Service zu lange braucht, um zu antworten, sieht der SCM ihn als unterbrochen. Dies wird hier diskutiert: http://msdn.microsoft.com/en-us/library/ms684264(VS.85).aspx
UPDATE:
Besonders die Service State Transitions MSDN beachten Sie Artikel, an dem der Artikel, die Mitchell Taylor zitiert Links. Es enthält ein Zustandsdiagramm, das ziemlich eindeutig & definierte Dienstzustandsübergänge autorisierend dokumentiert und mit dem übereinstimmt, was ich oben umrissen habe. In Bezug auf das Zustandsdiagramm wird auch erläutert, wie der SCM Dienststeuerungsanforderungen nicht zeitweise überträgt, um nur definierte Zustandsübergänge sicherzustellen.
Ich bin daran interessiert, was die Garantien auch sind. Ich habe nie gesehen, dass etwas wie dein Beispiel ein Problem verursacht; Ich weiß jedoch, dass der Erwerb von Ressourcen, die an die Thread-Identität gebunden sind (in unserem Fall ein Mutex), in der Vergangenheit zu Problemen mit meinem Team geführt hat. –
Ich habe die gleiche Frage schon einmal gestellt. Ich werde es ausgraben. – spender
Hier sind Sie (Kennzeichnung als dupe): [Aufruf von ServiceBase.OnStart und OnStop ... gleiche Instanz?] (Http: // stackoverflow.com/questions/10799937/calling-servicebase-onstart-and-onstop-selbe-instanz) – spender