2011-06-09 11 views
6

En una aplicación de forma triunfo, tengo una serie de roscas que se inicia así:Asegúrese de que todas las discusiones salieron

bool stop = false; 
Thread[] threads = new Thread[10]; 

for (int i = 0; i < threads.Length; i++) 
    threads[i] = new Thread(new ThreadStart(Job)); 

// How to make sure all threads have exited, when the boolean = false 

void Job() 
{ 
    while (!stop) 
     // Do something 
} 

Ahora bien, si el usuario pulsa STOP, el valor booleano para stop se define como true, por lo los hilos salen del método Job uno tras otro. ¿Cómo puedo asegurarme de que se salgan todos los hilos?

NOTA: Necesito el enhebrado tradicional para mi caso y TaskLibrary no encaja en mi situación.

Respuesta

4

¿Ha pensado en el uso de BackgroundWorkers en su lugar? Usted dijo "hilos tradicionales" ... No estoy muy seguro de lo que quiere decir, así que no sé si esta es una propuesta válida o no, pero aquí está de todos modos en caso de que Join() no resuelva su problema

BackgroundWorker[] workers = new BackgroundWorker[10]; 
bool allThreadsDone = false; 

// initialize BackgroundWorkers 
for (int i = 0; i < 10; i++) 
{ 
     workers[i] = new BackgroundWorker(); 
     workers[i].WorkerSupportsCancellation = true; 
     workers[i].RunWorkerCompleted += 
      new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted); 
     workers[i].DoWork += new DoWorkEventHandler(AlgorithmsUI_DoWork); 
     workers[i].RunWorkerAsync(); 
} 

// thread entry point..DoWork is fired when RunWorkerAsync is called 
void AlgorithmsUI_DoWork(object sender, DoWorkEventArgs e) 
{ 
     while (!stop) 
      // do something   
} 

// this event is fired when the BGW finishes execution 
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    bool threadsStillRunning = false; 
    foreach (BackgroundWorker worker in workers) 
    { 
     if (worker.IsBusy) 
     { 
      threadsStillRunning = true; 
      break; 
     } 
    } 
    if (!threadsStillRunning) 
     allThreadsDone = true; 
} 

protected override OnFormClosing(FormClosingEventArgs e) 
{ 
     if (!allThreadsDone) 
     { 
       e.Cancel = true; 
       MessageaBox.Show("Threads still running!"); 
     } 
} 

Esto debería evitar que su formulario se cierre si todavía hay subprocesos en ejecución.

7

Utilice el método Join para comprobar si se han detenido todos los hilos.

foreach (var t in threads) 
{ 
    t.Join(); 
} 
+0

¿Dónde colocar este código? Esta es una aplicación de formulario de victoria y se ha lanzado el subproceso de interfaz de usuario después de crear nuevos subprocesos. – Xaqron

+0

Si la interfaz de usuario se ha lanzado, ¿por qué preocuparse? Pero en serio, lo ubicaría en el método que maneja el botón de parada que se está presionando. –

+0

Quiero deshabilitar la salida del programa hasta que se salgan todos los subprocesos. Si el usuario cierra el formulario principal y hay algunos hilos activos en el administrador de tareas, el usuario siente que la aplicación ha fallado (aunque todos los hilos se cerrarán después de un tiempo) – Xaqron

1

no estoy seguro si esto es lo que está buscando, pero aquí es una solución simple he utilizado de nuevo en .NET 3.0 para asegurarse de que un gran número de determinista, pero las discusiones se había completado antes de continuar:

Global:

AutoResetEvent threadPoolComplete = new AutoResetEvent(false); 
static int numThreadsToRun; 

Como activar los hilos:

numThreadsToRun = [number of threads]; 
[start your threads]; 
threadPoolComplete.WaitOne(); 

al final del código de cada hilo:

if (Interlocked.Decrement(ref numThreadsToRun) == 0) 
{ 
    threadPoolComplete.Set(); 
} 
+0

+ Este es un buen ejemplo para tareas similares sin ganar. Para los formularios de ganar, como dijo 'alexD', el trabajador de fondo asíncrono es más fácil de implementar. – Xaqron

Cuestiones relacionadas