Es ist nicht wirklich wichtig, dass Ihr Dienst single-threaded ist, als ein Dienst seinen Code in anderen Thread Kontexte aufgerufen hat immer:
Der Service Manager wird starten, stoppen, anhalten und fortsetzen die Ausführung des Dienstes und fordern Sie den aktuellen Dienststatus an.
Der Dienst selbst wird über mindestens einen Thread verfügen, der die eigentliche Arbeit erledigt. Er muss auf die Anforderungen des Dienst-Managers reagieren, den Status der Dienstausführung wie angefordert ändern und die angeforderten Informationen zurückgeben. Ein Dienst muss in relativ kurzer Zeit auf Anforderungen vom Service Manager reagieren. Andernfalls wird der Dienst angehalten und beendet. Aus diesem Grund ist es möglicherweise besser, wenn mehr als ein Dienst-Thread vorhanden ist, wenn der Dienst Code lange ausführen oder blockieren kann.
Ob Sleep() oder Timer-Nachrichten auch abhängig von der Verfügbarkeit einer Nachricht Pumpe in den Service-Threads nicht zu verwenden. Wenn Sie keine Nachrichtenpumpe haben, sollten Sie Sleep() oder Timer-Rückrufe verwenden. Wenn Sie trotzdem eine Nachricht pumpen müssen, weil Sie mit anderen Prozessen oder Threads über Windows-Nachrichten kommunizieren müssen, oder Sie müssen OLE-Sachen machen, dann ist es am einfachsten, Timer-Nachrichten zu verwenden.
Vor ein paar Jahren schrieb ich einen Dienst für zeitgesteuerte Ausführung von Aufgaben, ähnlich wie Windows at
oder Unix cron
Funktionalität. Es verwendet nicht viel von der VCL, nur einige Basisklassen. Die Run() Methode des Dienstes sieht wie folgt aus:
procedure TScheduleService.Run;
var
RunState: TServiceRunState;
begin
while TRUE do begin
RunState := GetServiceRunState;
if (RunState = srsStopped) or (fEvent = nil) then
break;
if RunState = srsRunning then begin
PeriodicWork;
Sleep(500);
end else
fEvent.WaitFor(3000);
Lock;
if fServiceRunStateWanted <> srsNone then begin
fServiceRunState := fServiceRunStateWanted;
fServiceRunStateWanted := srsNone;
end;
Unlock;
end;
end;
Dies verwendet Sleep() in einer Schleife, aber eine Lösung
while integer(GetMessage(Msg, HWND(0), 0, 0)) > 0 do begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
würde funktionieren genauso gut mit, und Dann könnten Windows-Timer-Nachrichten verwendet werden.
Die erste Frage kam mir auch in den Sinn. http://weblogs.asp.net/jgalloway/archive/2005/10/24/428303.aspx – ilitirit
Eine interessante Lektüre. Es hat sehr gültige Punkte und einige der Kommentare. Ich mag dieses Zitat besonders: "Es ist besser, einen vorhandenen Dienst zu verwenden, als einen eigenen zu rollen, der das Gleiche tut. Aber ... Windows Task Scheduler saugt." Also, Taskplaner sollte die erste Sache sein, zu versuchen, und das Schreiben eines Dienstes sollte nur in extremen Fällen erfolgen. Aber diese Fälle existieren, ich schrieb einen Terminplanungsdienst nur, nachdem ich lange gegen den Aufgabenplanungsdienst gekämpft hatte und schließlich akzeptieren musste, dass er einfach nicht vielseitig genug war. – mghie