2010-05-17 12 views
15

Tengo una aplicación que realiza algunas tareas en segundo plano (escucha en la red & leyendo) en un Thread por separado. Sin embargo, parece que el subproceso no se cierra/cancela cuando cierro la aplicación (haga clic en el botón "x" en la barra de título). ¿Eso es porque la rutina principal de subprocesos es while(true) {...}? ¿Cuál es la solución aquí? Estaba buscando una bandera de "interrupción" para el subproceso como condición para el ciclo "while", pero no encontré ninguna.El hilo no se cierra al cerrar la aplicación

Respuesta

21

La manera más simple es establecer la propiedad IsBackground del hilo en verdadero. Esto evitará que mantenga la aplicación abierta. Una aplicación finaliza cuando finalizan todos los subprocesos que no son de fondo.

Una forma más controlada de detener el hilo es enviarle un mensaje para que se cierre de forma limpia y asegúrese de que ha finalizado antes de dejar que finalice el hilo principal.

Un método que no recomendaría es llamar al Thread.Abort. Esto tiene una serie de problemas, uno de los cuales es que no se garantiza que termine el hilo. De la documentación:

Llamar a este método generalmente finaliza el hilo.

Énfasis mío.

+1

+1 al método del mensaje.'while (stayAlive)' en lugar de 'true' es mucho más limpio, incluso si toma algunos segundos extra para que el ciclo se solucione. – user7116

0

Bueno, en lugar de while(true), tal vez usted debe:

while(appIsRunning) 
{ 
} 

Y, en el evento de cierre para su formulario,

appIsRunning = false; 
thread.Join(2000); 

donde la última línea es sólo para asegurarse de espera el hilo para terminar limpiamente Hay muchas otras formas de forzar el final de un hilo, pero el problema está ahí: no desea ser forzando cosas, quiere que sucedan lo más natural posible.

Después de la unión, puede verificar el estado de la secuencia para ver si ha finalizado. Si no lo hace, y luego (y solo en ese momento) forzar su finalización con un aborto, y tal vez notificar a su usuario (o escribir un registro) que algo no ha terminado como debería.

+0

Sí, pero recuerda usar 'volatile' o' lock' u otro método de sincronización. –

+0

@Mark: podría estar totalmente equivocado aquí, pero como el subproceso secundario solo lee y el subproceso principal solo escribe, ¿existe la posibilidad de un error? –

+1

Sin sincronizar, no se garantiza que un cambio en appIsRunning de un hilo sea visible en el otro hilo. Puedes leer más aquí: http://timl.net/2009/03/volatile-memory.html –

1

Se podría mejorar la while (true) bucle para

void DoWork() { 
    while(!ShouldIQuitManualResetEvent.WaitOne(0)) { 
     // do something 
    } 
    IDidQuitManualResetEvent.Set() 
} 

Un poco más elegante, corta a partir de los nombres de los identificadores.

3

Siempre se puede forzar la situación:

class Program 
{ 
    public static void Main() 
    { 
     // ... do stuff 
     Environment.Exit(Environment.ExitCode); 
    } 
} 

El mejor enfoque consiste en establecer la propiedad Thread.IsBackground true como Mark ya se ha mencionado.

0

Usted puede comenzar su hilo como:

ThreadPool.QueueUserWorkItem(DoStuff, input) 

y será abortar de forma automática con la aplicación de cerca.

Cuestiones relacionadas