2009-07-30 10 views
6

Necesito informar un llamado subproceso de trabajo para detener el trabajo en la siguiente oportunidad disponible. Actualmente estoy usando algo como esto:Opciones para informar a un subproceso para detener

public void Run() 
    { 
     while (!StopRequested) 
      DoWork(); 
    } 

La preocupación que tengo es que StopRequested se establece en True en un subproceso diferente. ¿Esto es seguro? Sé que no puedo bloquear un booleano. Quizás haya una manera diferente de informar a un hilo que se requiere una detención. Por ejemplo, me gustaría comprobar Thread.CurrentThread.ThreadState == ThreadState.StopRequested pero no está claro cómo puedo configurar el estado del hilo como tal.

+0

¿Por qué no puedes bloquear un booleano? En general, se considera una buena práctica crear un 'Objeto' separado para cualquier bloqueo, de todos modos. –

+0

No puedo bloquear el bool porque es 'un tipo de valor: podría crear un objeto llamado sync con el único propósito de bloquearlo al obtener/configurar el indicador bool --- pero me parece que bloquea en un bool debería ser seguro, y al menos Reed Copsey está de acuerdo –

+0

Sí, bloquear un bool debería ser seguro. Cancelación cooperativa. el Backgroundworker admite un concepto similar si es apropiado para la tarea que está realizando. –

Respuesta

3

Este es un mejor enfoque que tratar de configurar el ThreadState. Si mira los documentos para ThreadState, dice específicamente que StopRequested es solo para uso interno.

Establecer un valor booleano a partir de otro subproceso es una operación segura. No deberías necesitar bloquear este caso.

+0

Me gustaría leer más sobre este enfoque. ¿Tiene enlaces a preguntas similares, documentos, blogs? –

2

El uso del objeto Event será probablemente mejor. Especialmente si tu hilo bloquea. (Entonces todavía puede esperar el evento dentro de la llamada de bloqueo)

3

Es posible que desee utilizar un BackgroundWorker para hacer el trabajo por usted, usando RunWorkerAsync() y manejando el caso worker.CancellationPending == true durante su lógica.

BackgroundWorker worker = new BackgroundWorker(); 
worker.WorkerSupportsCancellation = true; 
worker.DoWork += MyWorkFunction; 
worker.RunWorkerCompleted += MyWorkDoneSuccessfullyFunction; 
worker.RunWorkerAsync(); 

Otra solución sería utilizar un bool volátil para señalar que tiene que dejar, lo que podría configurar en cualquier lugar dentro de la clase.

private volatile bool cancelWork = false; 

public void CancelWork() 
{ 
    cancelWork = true; 
} 
+0

e.Cancelado es solo después de que el trabajador ha sido detenido, vea mi publicación a continuación – SwDevMan81

+0

@ SwDevMan81: Está en lo correcto, editó ese comentario.Se puede encontrar una implementación correcta para DoWork aquí: http://msdn.microsoft.com/en-us/library/system.componentmodel.doworkeventargs.argument.aspx –

2

Puede utilizar Thread.Abort() y envolver cualquier limpieza necesaria en el método DoWork() en un bloque finally.

0

Si utiliza el BackgroundWorker, que llamarían la función CancelAsync del BackgroundWorker establece el CancellationPending propiedad en true, que es lo que se debe buscar en su bucle:

public void Run(object sender, DoWorkEventArgs e) 
{  
    BackgroundWorker worker = sender as BackgroundWorker; 
    if(worker != null) 
    { 
     while (!worker.CancellationPending) 
     { 
     DoWork(); 
     } 
    } 
} 

Lo anterior sería el DoWork código de evento al que se llama cuando ejecuta la función RunWorkerAsync.

1

La preocupación que tengo es que StopRequested se establece en True en un hilo diferente. ¿Esto es seguro?

Debe asegurarse de que el campo StopRequested tenga la palabra clave volatile. Ver this other answer por la razón por la cual.

Cuestiones relacionadas