Tengo un proceso que se ejecuta en su propio hilo y puede iniciarse/detenerse sin bloqueo. Eventualmente, esto irá a un servicio de Windows, pero estoy configurando esto en una aplicación de consola por ahora hasta que esté completamente desarrollado.Usar un semáforo en lugar del ciclo while. ¿Esto es bueno o malo?
Después de la llamada a Inicio(), quiero que el hilo del programa principal se bloquee hasta que se presione Ctrl-C. Sé que esto funcionará:
public static void Main(string[] args)
{
bool keepGoing = true;
var service = new Service();
System.Console.TreatControlCAsInput = false;
System.Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
{
e.Cancel = true;
service.Stop();
keepGoing = false; // Break the while loop below
};
service.Start();
while(keepGoing)
{
Thread.Sleep(100); // 100 is arbitrary
}
}
Sin embargo, creo que el indicador y el valor de suspensión arbitrario son molestos. Sé que el costo de la CPU es prácticamente 0 en el ciclo while, pero prefiero tener un bloque "difícil" que se libera tan pronto como finaliza el controlador Ctrl-C. Ideé el siguiente, usando un semáforo para bloquear hasta que se haga el manejador anónima Ctrl-C:
public static void Main(string[] args)
{
var service = new Service();
var s = new Semaphore(1, 1);
System.Console.TreatControlCAsInput = false;
System.Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
{
e.Cancel = true;
service.Stop();
s.Release(); // This will allow the program to conclude below
};
service.Start();
s.WaitOne(); // This will not block
s.WaitOne(); // This will block w/o CPU usage until the sempahore is released
}
¿Es un mal diseño? ¿Es excesivo? ¿Es peligroso?
EDIT:
también puedo conectar AppDomain.CurrentDomain.UnhandledException de la siguiente manera:
AppDomain.CurrentDomain.UnhandledException += delegate {
service.Stop();
s.Release();
};
editar el segundo:
Debo señalar que es fundamental que la Se llama al método Stop()
al salir. @Adam Ralph tiene un patrón perfectamente bueno para una consola/servicio híbrido, pero no tenía esta información al responder la Q.
Si puede evitar el ciclo while digo que vale la pena seguir. – ChaosPandion
Para la creación de prototipos esto último es una gran mejora. En una aplicación de producción, evitaría toda la idea de romper "CTRL + C". Use una señal para matar el hilo en su lugar. La forma en que la señal es 'Set()' depende de las otras capas involucradas. Solo téngalo en cuenta al diseñar su servicio. Agregue un medio, como un método al que se pueda llamar, a su vez, invoque 'Set()'. –
@ P.Brian.Mackey: aunque esta no es una aplicación de producción, si * fuera *, ¿no sería prudente al menos manejar Ctrl-C correctamente en una aplicación de consola no interactiva? Tal como está, Ctrl-C simplemente cerrará el programa sin una oportunidad de limpieza antes de salir. En última instancia, simplemente me preguntaba si la solución de semáforo a la opción "while (flag) Thread.Sleep (...)". –