2010-04-29 3 views
7

Ho un'applicazione console che si avvia, ospita un sacco di servizi (avvio di lunga durata), quindi attende che i client ci chiamino. Ho dei test di integrazione che avviano questa applicazione di console e fanno chiamate "client". Come posso aspettare che l'applicazione della console completi l'avvio prima di effettuare le chiamate client?Come posso attendere fino a quando un'applicazione della console non è inattiva?

Voglio evitare di fare Thread.Sleep(int) perché questo dipende dal tempo di avvio (che può cambiare) e spreco tempo se l'avvio è più veloce.

Process.WaitForInputIdle funziona solo su applicazioni con un'interfaccia utente (e ho confermato che genera un'eccezione in questo caso).

Sono aperto a soluzioni scomode come, fare in modo che l'applicazione console scriva un file temporaneo quando è pronto.

+0

L'applicazione di console ospita i servizi WCF. Il "client" effettua chiamate WCF. Se l'applicazione della console non ha completato l'avvio, il client ottiene eccezioni Endpoint non trovato. –

risposta

10

Un'opzione potrebbe essere quella di creare un evento EventWaitHandle. Questo crea un oggetto di sincronizzazione che è possibile utilizzare attraverso i processi. Quindi le tue applicazioni "client" attendono fino a quando l'evento non viene segnalato prima di procedere. Una volta che l'applicazione della console principale ha completato l'avvio, può segnalare l'evento.

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

A titolo di esempio, l'applicazione di console "Server" potrebbe avere la seguente. Questo non è compilato quindi è solo un punto di partenza :)

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(); 
} 

I clienti sarebbero quindi fare qualcosa di simile

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

Che cosa significa "fare"? Ho usato il nome "MyCompany \ HostStarted" e l'applicazione console ha lanciato un'eccezione DirectoryNotFound! –

+3

Avrei dovuto dirlo. Il prefisso Global \ o Local \ controlla l'ambito dell'evento. Globale \ rende l'evento "visibile" su tutte le sessioni, mentre Locale \ lo renderà visibile solo nella sessione corrente. Questa è una distinzione importante quando l'app è in esecuzione su una sessione di terminal server, ad esempio, dove potresti voler utilizzare Local \ in base ai tuoi requisiti. –

+1

questo è fantastico e un po 'terribile. lo adoro. –

1

Includere un controllo pronto nell'interfaccia client dell'app o restituire un errore non pronto se chiamato prima che sia pronto.

+0

Quindi l'applicazione dovrebbe eseguire il ciclo di registrazione finché non restituisce un errore "non sono pronto"? Non sono sicuro se sia un buon approccio ... – Jack

0
  • Dal momento che i due (l'applicazione console, e l'integrazione di test app che rende client chiama - come ho capito) sono un'applicazione separata, quindi non ci dovrebbe essere un meccanismo - un ponte - che avrebbe detto il gioco come mediatore (socket, file esterno, registro, ecc.).

  • Un'altra possibilità potrebbe essere quella di ottenere un tempo medio che la console impiega per caricare i servizi e utilizzare tale tempo nell'app di test; bene, sto solo pensando ad alta voce!

4

Che ne dici di impostare un mutex e rimuoverlo una volta avviato l'avvio. Fai in modo che l'app client attenda fino a quando non riesce ad afferrare il mutex prima di iniziare a fare le cose.

+0

Simile in linea di principio alla risposta che ho fornito, tuttavia utilizzando un EventWaitHandle consentirai a più app client di sincronizzarsi sull'app principale. –

1

Creare un servizio WCF che è possibile utilizzare per l'interrogazione dello stato del processo del server. Avvia questo servizio solo se un particolare comando viene passato sulla riga di comando. Le seguenti caratteristiche assicurano un avvio molto veloce di questo servizio:

  • Host questo servizio come la prima operazione dell'applicazione client
  • Usare il net.tcp o rete.pipe vincolante perché partono molto rapidamente
  • Tenere questo servizio il più semplice possibile per garantire che, fintanto che l'applicazione di console non termina, rimarrà a disposizione

Il test runner può tentare di connettersi a questo servizio. Riprovare il tentativo se fallisce fino alla fine dell'applicazione console o scade un periodo di timeout ragionevolmente breve. Finché l'applicazione console non si interrompe in modo imprevisto, puoi fare affidamento su questo servizio per fornire ulteriori informazioni prima di iniziare i test in un periodo di tempo ragionevolmente breve.

+0

Troppo lavoro, ospitiamo questa cosa come un servizio in produzione e non abbiamo mai questo tipo di problema di corse. –