2008-08-16 16 views
6

De vez en cuando obtengo una System.Threading.ThreadStateException cuando intento reiniciar una cadena. El código en cuestión es la siguiente:Ocurre una excepción ThreadStateException al intentar reiniciar una secuencia

// Make sure the thread is done stopping 
while (this.mThread.ThreadState == ThreadState.Running) 
{ 
    Thread.Sleep(0); 
} 
// Respawn a thread if the current one is stopped or doesn't exist 
if (this.mThread == null || this.mThread.ThreadState == ThreadState.Stopped) 
{ 
    this.mThread = new Thread(new ParameterizedThreadStart(Monitor)); } 
// Start the thread 
if (check) 
{ 
    this.mThread.Start(60000); 
} 
else 
{ 
    this.mThread.Start(0); 
} 

Así que dos preguntas - es esta la forma correcta de hacer las cosas, y lo es, ¿hay una manera de evitar que el error se produzca?

Respuesta

3

El problema es que tiene un código que primero comprueba si debe crear un nuevo objeto de subproceso y otro elemento de código que determina si iniciar el objeto de subproceso. Debido a las condiciones de la carrera y cosas similares, su código podría terminar tratando de llamar. Inicie un objeto de subproceso existente. Teniendo en cuenta que no publica los detalles detrás de la variable check, es imposible saber qué podría desencadenar este comportamiento.

Debe reorganizar su código para que .Start garantice que solo se invoca a los objetos nuevos. En resumen, debe poner el método Start en la misma instrucción if que la que crea un nuevo objeto thread.

Personalmente, intentaría reorganizar todo el código para no tener que crear otro subproceso, pero envolver el código dentro del objeto de subproceso dentro de un bucle para que el subproceso siga funcionando.

1

Se lanza una excepción ThreadStateException porque está tratando de iniciar un hilo que no está en estado de arranque. Las situaciones más probables serían que ya se está ejecutando, o que ha salido por completo.

Hay un par de cosas que podrían estar pasando. Primero, el hilo podría haber pasado de Correr a Detener Solicitado, que aún no se ha detenido por completo, por lo que su lógica no crea un nuevo hilo, y usted está tratando de iniciar un hilo que acaba de ejecutar o está a punto de terminar ejecutando (ninguno de los cuales es un estado válido para reiniciar).

La otra posibilidad es que el hilo haya sido abortado. Los hilos que están abortados pasan al estado Anulado, no al estado Detenido, y por supuesto tampoco son válidos para reiniciarse.

Realmente, el único tipo de subproceso que todavía está activo que se puede "reiniciar" es uno que está suspendido. Es posible que desee utilizar esta condicionada en su lugar:

if (this.mThread == null || this.mThread.ThreadState != ThreadState.Suspended)

6

Es posible que un hilo para estar en más de un estado a la vez, por lo tanto la propiedad ThreadState es en realidad un mapa de bits de estados posibles. Por lo tanto, probar la igualdad con un solo estado no le dará el resultado correcto. Tendrá que hacer algo como:

if((mThread.ThreadState & ThreadState.Running) != 0) 

Sin embargo, comprobar el estado del hilo es el incorrecto para hacer cualquier cosa. No estoy del todo claro de lo que intentas lograr, pero supongo que estás esperando a que finalice un hilo antes de reiniciarlo. En ese caso, debería hacer:

mThread.Join(); 
mThread = new Thread(new ParameterizedThreadStart(Monitor)); 
if(check) 
    mThread.Start(60000); 
else 
    mThread.Start(0); 

Aunque si describe el problema que estamos tratando de resolver con más detalle Estoy casi seguro de que habrá una solución mejor. Esperar que un hilo termine solo para reiniciarlo nuevamente no me parece eficiente. Tal vez solo necesitas algún tipo de comunicación entre hilos?

John.

Cuestiones relacionadas