Considere una aplicación de consola que inicia algunos servicios en un hilo separado. Todo lo que necesita hacer es esperar a que el usuario presione Ctrl + C para apagarlo.
¿Cuál de las siguientes es la mejor manera de hacer esto?
static ManualResetEvent _quitEvent = new ManualResetEvent(false);
static void Main() {
Console.CancelKeyPress += (sender, eArgs) => {
_quitEvent.Set();
eArgs.Cancel = true;
};
// kick off asynchronous stuff
_quitEvent.WaitOne();
// cleanup/shutdown and quit
}
O esto, usando Thread.Sleep (1):
static bool _quitFlag = false;
static void Main() {
Console.CancelKeyPress += delegate {
_quitFlag = true;
};
// kick off asynchronous stuff
while (!_quitFlag) {
Thread.Sleep(1);
}
// cleanup/shutdown and quit
}
c#
multithreading
sleep
manualresetevent
en órbita
fuente
fuente
bool
que no se declara comovolatile
, existe la posibilidad definitiva de que las lecturas posteriores_quitFlag
en elwhile
ciclo se optimicen, lo que lleva a un ciclo infinito.Alternativamente, una solución más simple es simplemente:
fuente
Puede hacer eso (y eliminar el
CancelKeyPress
controlador de eventos):No estoy seguro si eso es mejor, pero no me gusta la idea de llamar
Thread.Sleep
en un bucle ... Creo que es más limpio bloquear la entrada del usuario.fuente
Prefiero usar Application.Run
de los documentos:
fuente
Parece que lo estás poniendo más difícil de lo necesario. ¿Por qué no solo
Join
el hilo después de haber señalado que se detenga?fuente
También es posible bloquear el hilo / programa basándose en un token de cancelación.
WaitHandle se señala cuando se cancela el token.
He visto esta técnica utilizada por Microsoft.Azure.WebJobs.JobHost, donde el token proviene de una fuente de token de cancelación de WebJobsShutdownWatcher (un observador de archivos que finaliza el trabajo).
Esto le da cierto control sobre cuándo puede finalizar el programa.
fuente
CTL+C
porque está realizando una operación de larga duración, o es un demonio, que también debería cerrar correctamente sus subprocesos de trabajo. Haría eso con un CancelToken y, por lo tanto, esta respuesta aprovecha unaWaitHandle
que ya existiría, en lugar de crear una nueva.De los dos el primero es mejor
porque en el segundo, el hilo se despierta cada milisegundo y se convertirá en una interrupción del sistema operativo, que es costosa
fuente
Console
métodos si no tiene una consola adjunta (porque, por ejemplo, el programa es iniciado por un servicio)Debe hacerlo como lo haría si estuviera programando un servicio de Windows. Nunca usarías una declaración while en lugar de eso, usarías un delegado. WaitOne () generalmente se usa mientras se espera que los hilos se eliminen - Thread.Sleep () - no es aconsejable - ¿Ha pensado en usar System.Timers.Timer usando ese evento para verificar el evento de apagado?
fuente