Realmente no importa que su servicio es de un solo hilo, como un servicio tendrá su código siempre se llama en diferentes contextos de rosca:
El jefe de servicio se iniciar, detener, pausar y reanudar la ejecución del servicio, y solicita el estado del servicio actual.
El servicio en sí tendrá al menos un hilo haciendo el trabajo real, que debe reaccionar a las solicitudes del administrador del servicio, cambiar el estado de ejecución del servicio solicitado y devolver la información solicitada. Un servicio debe reaccionar a las solicitudes del administrador de servicios en un tiempo razonablemente corto; de lo contrario, considerará que el servicio se cuelga y lo matará. Es por eso que, si el servicio puede tener código de ejecución o bloqueo a largo plazo, puede ser mejor tener más de un hilo de servicio.
si se debe usar Sleep() temporizador o mensajes de qué dependen también de la disponibilidad de un suministro de mensajes en los hilos de servicio. Si no tiene un mensaje de bomba debe usar Sleep() o devoluciones de llamada del temporizador. Si tiene un mensaje de bomba de todos modos, porque necesita comunicarse con otros procesos o subprocesos a través de mensajes de Windows, o necesita hacer cosas OLE, entonces puede ser más fácil utilizar mensajes de temporizador.
Hace algunos años escribí un servicio para la ejecución de tareas de fondo temporizadas, similar a la funcionalidad de Windows at
o Unix cron
. No utiliza gran parte de la VCL, solo algunas clases base. El Run() método del servicio es el siguiente:
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;
Este utiliza Sleep() en un bucle, pero una solución utilizando
while integer(GetMessage(Msg, HWND(0), 0, 0)) > 0 do begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
funcionaría igual de bien, y entonces se podrían usar los mensajes del temporizador de Windows.
También me vino a la mente la primera pregunta. http://weblogs.asp.net/jgalloway/archive/2005/10/24/428303.aspx – ilitirit
Una lectura interesante. Tiene puntos muy válidos, y también algunos de los comentarios. Me gusta especialmente esta cita: "es mejor utilizar un servicio existente que hacer el suyo que hace lo mismo. Pero ... el Programador de tareas de Windows apesta". Así que sí, el programador de tareas debe ser lo primero que debe intentar, y escribir un servicio solo debe hacerse en casos extremos. Pero estos casos existen, escribí un servicio de programación solo después de haber luchado contra el servicio del programador de tareas durante mucho tiempo y finalmente tuve que aceptar que simplemente no era lo suficientemente versátil. – mghie