2012-09-21 29 views
5

Tengo una aplicación WinForms que consta de un subproceso de interfaz de usuario principal y 4 tareas. Mi forma principal tiene una variable de nivel de miembro privado como esto:Formulario de cierre con tareas que ejecutan

private bool keepThreadsRunning = false; 

En el evento Load() de mi forma principal, tengo el siguiente:

keepThreadsRunning = true; 
var task1Worker = Task.Factory.StartNew(() => DoStuff1()); 
var task2Worker = Task.Factory.StartNew(() => DoStuff2()); 
var task3Worker = Task.Factory.StartNew(() => DoStuff3()); 
var task4Worker = Task.Factory.StartNew(() => DoStuff4()); 

En el interior de cada uno de mis DoStuff() métodos, tengo básicamente esto:

while (keepThreadsRunning) 
{ 
    // do work here 
    Thread.Sleep(30000); // a couple of my tasks only need to run every 30 seconds or so 
} 

por último, en mi controlador de eventos Form_Closing(), tengo el siguiente:

keepThreadsRunning = false; 
this.Close(); 

Viendo mi aplicación en el administrador de tareas, parece que el proceso finaliza cuando cierro mi formulario, pero estoy un poco confundido acerca de las cuatro tareas. ¿Mi llamada a this.Close() realmente hace que esas tareas finalicen (incluso si están en la llamada Thread.Sleep() cuando suceden)? ¿Y hay una forma mejor de lograr esto que la forma en que estoy codificando en este momento?

EDITAR - He examinado brevemente la cancelación de tareas (cuando se cierra mi aplicación), pero tengo entendido que mis tareas necesitarían comprobar periódicamente el token de cancelación para determinar si se han cancelado. Dado que algunas de mis tareas deben ejecutarse cada 30 segundos, no pude entender cómo implementaría esa espera de 30 (actualmente, Thread.Sleep()) y aún tengo la tarea de verificar el token de cancelación.

Respuesta

2

En primer lugar, cerrando el hilo de interfaz de usuario principal será terminar sus otras tareas. Si necesita que sigan funcionando, quizás considere ejecutarlos en una aplicación de consola separada o en un servicio de Windows.

Incluso si encontró una manera de retrasar el cierre del formulario mientras termina de ejecutar los métodos que necesita ejecutar, esto solo funcionaría si el usuario final cerró el formulario de la manera que quería, y Windows es Windows allí hay un millón y una formas de cerrar una aplicación, por lo que no hay garantía de que esto funcione.

Para ejecutar un método de forma asíncrona cada x cantidad de segundos, sólo podría utilizar un temporizador para todo el asunto, así:

using System; 
using System.Timers; 
using System.Windows.Forms; 

namespace WindowsFormsApplication3 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      var timer1 = new System.Timers.Timer { Interval = 30000, Enabled = true }; 
      var timer2 = new System.Timers.Timer { Interval = 20000, Enabled = true }; 
      var timer3 = new System.Timers.Timer { Interval = 10000, Enabled = true }; 
      var timer4 = new System.Timers.Timer { Interval = 5000, Enabled = true }; 

      timer1.Elapsed += timer1_Elapsed; 
      timer2.Elapsed += timer2_Elapsed; 
      timer3.Elapsed += timer3_Elapsed; 
      timer4.Elapsed += timer4_Elapsed; 
     } 

     void timer4_Elapsed(object sender, ElapsedEventArgs e) 
     { 
      //do work here 
     } 

     void timer3_Elapsed(object sender, ElapsedEventArgs e) 
     { 
      //do work here 
     } 

     void timer2_Elapsed(object sender, ElapsedEventArgs e) 
     { 
      //do work here 
     } 

     void timer1_Elapsed(object sender, ElapsedEventArgs e) 
     { 
      //do work here 
     } 
    } 
} 
3

En lugar de utilizar un valor booleano y Thread.Sleep(), utilice un WaitHandle, específicamente un ManualResetEvent, creado de esta manera:

var threadTerminationHandle = new ManualResetEvent(false); 

En su hilo de rosca:

do { 
    // do work here 
} while (!threadTerminationHandle.WaitOne(TimeSpan.FromSeconds(30)) 

Esto esperar hasta que el WaitHandle se establece , o transcurren 30 segundos, lo que ocurra primero.

En su formulario:

threadTerminationHandle.Set(); 
Close(); 
2

Al cerrar aplicaciones, tareas será cerrado en consecuencia, porque la tarea se procesa bajo subproceso de fondo del grupo de subprocesos. Por lo tanto, no es necesario que compruebe periódicamente el token de cancelación para determinar si se han cancelado

Cuestiones relacionadas