C#Tiempo de espera de servicio de Windows en el inicio
service timeout (5)
Algunas cosas para probar:
Agregue mensajes de registro a la parte superior de
Main()
, antes deServiceBase.Run()
, etc. Suponiendo que obtenga un archivo de registro, ¿cómo se comparan esas marcas de tiempo con el registro de eventos de Windows?Cree un nuevo servicio con el Asistente de nuevo proyecto y desplácelo tal como está. En las máquinas problemáticas, ¿arranca de forma fiable?
Obtener monitor de proceso y ver un inicio normal. Busque cualquier red o archivo de E / S inesperado.
Asegúrese de que su
SchedulerService
no haga ningún trabajo en el constructor, y no tenga dependencias estáticamente inicializadas.Configure las opciones de recuperación para reiniciarse en el primer fallo. ¿Eso funciona de manera confiable?
Tengo dificultades para intentar determinar la causa de un tiempo de espera en un servicio de Windows que he creado con C #. He pasado una cantidad considerable de tiempo mirando varias publicaciones y temas sobre el tema, pero no estoy seguro de qué más intentar.
¿Cuál es el problema?
A veces, en ciertas máquinas que ejecutan mi servicio de Windows, no se inicia correctamente después de que la máquina se haya reiniciado. Recibo los mensajes de EventLog comunes acerca de que el Servicio no se inició de manera oportuna y que expiró después de 30000 milisegundos. Las máquinas con Windows Server 2003 parecen ser el patrón más común, pero no siempre están aisladas solo para este sistema operativo. Por ejemplo, funciona perfectamente bien en otras máquinas W2K3.
El error de inicio puede ser bastante aleatorio, ya que a veces se iniciará y otras veces fallará, por lo que es muy difícil reproducir el problema a pedido. También estoy utilizando Log4Net para detectar errores y registrarlos en un RollingFileAppender. Sin embargo, cuando el servicio no se inicia, nunca se crea un archivo de registro y no se guarda la información de registro. Es como si mi hilo de entrada de Servicio estuviera bloqueando y no fuera llamado.
Otros detalles:
- El servicio de Windows está escrito en C # y usa .Net 2.0
- No hay otras dependencias de servicio para mi servicio cuando está instalado.
- El exe de servicio es una versión de compilación sin firma o autenticada.
- El método OnStart se ejecuta lo más rápido posible creando un Thread e iniciando ese Thread. Ninguna otra inicialización tiene lugar dentro de OnStart.
- Cuando el servicio realmente no se inicia, abrir la lista de servicios e iniciarlo manualmente funciona cada vez y el servicio se inicia probablemente en menos de un segundo.
Tengo el siguiente código agregado a mi Program.cs que incluye el punto de entrada principal para el servicio. Me conecto a un evento UnhandledException en CurrentDomain y estoy usando log4net para registrar cualquier error no manejado. También hay un try / catch alrededor de ServiceBase.Run en el caso de que de alguna manera se bombardee para que pueda registrar ese error.
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new SchedulerService()
};
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
try
{
ServiceBase.Run(ServicesToRun);
}
catch (Exception ex)
{
Log.Fatal("Unhandled Service Exception", ex);
}
}
private static log4net.ILog _log = null;
static log4net.ILog Log
{
get
{
if (_log == null)
{
if (!log4net.LogManager.GetRepository().Configured)
{
log4net.Config.XmlConfigurator.Configure();
}
_log = log4net.LogManager.GetLogger(typeof(Program));
}
return _log;
}
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Exception ex = e.ExceptionObject as Exception;
if (ex == null) ex = new Exception(e.ExceptionObject.ToString());
Log.Fatal("Unhandled Service Exception", ex);
}
El código en mi implementación de ServiceBase heredada es el siguiente:
protected override void OnStart(string[] args)
{
Thread serviceThread = new Thread(new ThreadStart(BackgroundStart));
serviceThread.IsBackground = true;
serviceThread.Start();
}
private void BackgroundStart()
{
//Initialize and start worker objects to perform monitoring...
//<Snip>
}
Mi implementación de log4net está utilizando un ConsoleAppender y un RollingFileAppender donde sus detalles de configuración se almacenan en el App.config.
En esta etapa no estoy seguro de qué más probar. Si necesita más detalles, hágamelo saber.
Gracias.
Actualización: solo para actualizar a todos, voy a probar algunas de las sugerencias, como el registro directo en EventLog o un archivo en lugar de Log4Net para ver si esa es la causa. También intentaré configurar el valor deEvidencia genérica en la aplicación.config en falso. Solo estoy esperando un tiempo de inactividad adecuado para acceder al servidor del cliente para probar estas cosas.
Como log4net no está diseñado para ser ( en sus palabras ) un sistema de registro confiable, pensé que era una buena práctica escribir excepciones no manejadas en el registro de eventos (así como en su registro), especialmente con los servicios.
En general, generar un hilo de fondo a partir de OnStart
es lo correcto.
Para solucionar problemas, puede intentar darle a su servicio más tiempo de inicio llamando RequestAdditionalTime método OnStart
desde OnStart
. Además, es posible que desee comprobar si se han escrito mensajes en el Registro de eventos de Windows (registro "Aplicación", la fuente debe ser el nombre de su servicio).
Solucioné un problema similar desactivando la generación de pruebas del editor en el archivo de configuración. El servicio tampoco tenía firma de autenticidad, pero al agregar la siguiente línea, se solucionó el problema en la máquina donde se reproducía de manera consistente.
<runtime>
<generatePublisherEvidence enabled="false" />
</runtime>
También recomendado en esta fuente de MSDN :
"Recomendamos que los servicios utilicen el elemento para mejorar el rendimiento de inicio. El uso de este elemento también puede ayudar a evitar demoras que pueden causar un tiempo de espera y la cancelación del inicio del servicio ".
También sospecho que log4net de alguna manera está colgando. Es posible que la unidad donde se creará el registro no esté lista aún cuando la máquina se esté iniciando. ¿Has intentado iniciar tu servicio retrasado?