2010-04-29 9 views
7

Tengo una aplicación de consola que se inicia, aloja un conjunto de servicios (inicio prolongado) y luego espera a que los clientes llamen. Tengo pruebas de integración que inician esta aplicación de consola y hacen llamadas a "clientes". ¿Cómo espero a que la aplicación de la consola complete su inicio antes de realizar las llamadas de los clientes?¿Cómo espero hasta que una aplicación de consola esté inactiva?

Quiero evitar hacer Thread.Sleep(int) porque eso depende del tiempo de inicio (que puede cambiar) y pierdo tiempo si el inicio es más rápido.

Process.WaitForInputIdle funciona solo en aplicaciones con una IU (y confirmé que arroja una excepción en este caso).

Estoy abierto a soluciones torpes como, que la aplicación de la consola escriba un archivo temporal cuando esté listo.

+0

La aplicación de consola aloja servicios WCF. El "cliente" hace llamadas WCF. Si la aplicación de consola no ha completado el inicio, el cliente obtiene excepciones de Punto final no encontrado. –

Respuesta

10

Una opción sería crear un EventWaitHandle con nombre. Esto crea un objeto de sincronización que puede usar en todos los procesos. Luego, tiene sus aplicaciones 'cliente' esperando hasta que se marque el evento antes de continuar. Una vez que la aplicación de la consola principal ha completado el inicio, puede señalar el evento.

http://msdn.microsoft.com/en-us/library/41acw8ct(VS.80).aspx

A modo de ejemplo, la aplicación de consola "Servidor" puede tener los siguientes. Esto no es compilada por lo que es sólo un punto de partida :)

using System.Threading; 
static EventWaitHandle _startedEvent; 
static void main() 
{ 
    _startedEvent = new EventWaitHandle(false, EventResetMode.ManualReset, @"Global\ConServerStarted"); 

    DoLongRunnningInitialization(); 

    // Signal the event so that all the waiting clients can proceed 
    _startedEvent.Set(); 
} 

Los clientes entonces estarían haciendo algo como esto

using System.Threading; 
static void main() 
{ 
    EventWaitHandle startedEvent = new EventWaitHandle(false, EventResetMode.ManualReset, @"Global\ConServerStarted"); 

    // Wait for the event to be signaled, if it is already signalled then this will fall throught immediately. 
    startedEvent.WaitOne();  

// ... continue communicating with the server console app now ... 
} 
+2

¿Qué significa "hacer" ese nombre? Usé el nombre "MyCompany \ HostStarted" y la aplicación de consola lanzó una excepción DirectoryNotFound. –

+3

Debería haber mencionado eso. El prefijo Global \ o Local \ controla el alcance del evento. Global \ hace que el evento sea "visible" en todas las sesiones, mientras que Local \ lo hará solo visible en la sesión actual. Esta es una distinción importante cuando la aplicación se ejecuta en una sesión de servidor de terminal, por ejemplo, donde es posible que desee el uso Local \ dependiendo de sus requisitos. –

+1

esto es impresionante y algo terrible. Lo amo. –

1

Incluya un check in listo en la interfaz del cliente de la aplicación, o haga que devuelva un error no preparado si se llama antes de que esté listo.

+0

Entonces, ¿la aplicación debería verificar el ciclo hasta que no devuelva el mensaje "No estoy listo"? no estoy seguro de si es un buen enfoque ... – Jack

0
  • Puesto que los dos (la aplicación de consola, y la prueba de aplicaciones de integración que hace cliente llama - como yo lo entiendo) son solicitud por separado, por lo que no debería haber un mecanismo - un puente - que contara juego como mediador (socket, archivo externo, registro, etc.).

  • Otra posibilidad podría ser que usted obtenga un tiempo promedio que tarda la consola para cargar los servicios y usar ese tiempo en su aplicación de prueba; ¡Bueno, solo pensando en voz alta!

4

¿Qué pasa al establecer un mutex y eliminarlo una vez que se inicia el arranque? Haga que la aplicación del cliente espere hasta que pueda tomar el mutex antes de que comience a hacer cosas.

+0

Similar en principio a la respuesta que he proporcionado, sin embargo, al usar un EventWaitHandle, se permitirán que varias aplicaciones cliente se sincronicen en la aplicación principal. –

1

Crear un servicio WCF que se puede utilizar para consultar el estado de la proceso del servidor Solo inicie este servicio si se pasa un comando en particular en la línea de comando. Los siguientes rasgos asegurarán un inicio muy rápido de este servicio:

  • anfitrión este servicio como la primera operación de la aplicación cliente
  • Uso del net.tcp o red.tubo de unión porque empiezan muy rápidamente
  • esta servicio tan simple como sea posible para asegurar que siempre que la aplicación de consola no termina, porque estará disponible

El corredor de prueba puede intentar conectarse a este servicio Vuelva a intentar el intento si falla hasta que la aplicación de la consola finalice o expire un período de tiempo de espera razonablemente corto. Siempre que la aplicación de la consola no finalice inesperadamente, puede confiar en este servicio para proporcionar información adicional antes de comenzar sus pruebas en un período de tiempo razonablemente corto.

+0

Demasiado trabajo, lo presentamos como un servicio en producción y nunca tuvimos este tipo de problema de carrera. –

Cuestiones relacionadas