2011-01-23 23 views
5

tengo hilo de esta manera, después de ver ejemplo link textlanzar una excepción en el hilo C#

ThreadStart _threadStart = new ThreadStart(delegate() 
{ 
     try 
     { 
      threadFunction(httpContext); 
     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 
}); 
Thread _thread = new Thread(_threadStart); 
    _thread.Start(); 

cuando ocurra una excepción dosis no re-lanzado en el hilo que lo inició. Entonces, ¿qué estoy haciendo mal o cómo hacerlo?

Nota: se está lanzando gracias a todos los comentarios de avanzada

+6

Nota usted debe * * Nunca volver a lanzar una excepción como se hace allí. Solo hacer 'throw;' en el bloque catch es suficiente ... – Joey

+0

sé que puedo lanzar una excepción personalizada heredada de "System.Exception" con el mensaje – Hiyasat

+1

Tienes que lanzar una * nueva * excepción con la información que deseas agregar. Pase la excepción * original * como InnerException. Haga esto solo si la información agregada es de gran valor ya que dificulta la solución de problemas. –

Respuesta

7

Se lanzará la excepción, pero eso solo terminará el hilo. La excepción no se vuelve a lanzar en el hilo que la inició.

+0

¿Por qué es eso? y cual es la mejor solucion para hacerlo? – Hiyasat

+1

@Hiyasat: Si un hilo arroja alguna excepción en su hilo de inicio en cualquier momento, sería muy difícil implementar el hilo de inicio para manejarlo. Debe volver a enviar la excepción al hilo de inicio tal como lo hace con cualquier otro resultado, por ejemplo, utilizando un valor varable al que ambos hilos tengan acceso. – Guffa

1

La excepción, salvo que supongo que no lo ve, ya que se lanza en otro hilo. Por lo tanto, el subproceso de UI (o cualquier subproceso invocado el otro subproceso), no puede detectar la excepción, ya que no lo ve.

Si registra la excepción en un archivo, por ejemplo, estoy seguro de que lo verá. :)

+0

Se verá la excepción en cualquier subproceso que se haya generado. Creo que no hay ninguna excepción, el hilo acaba de terminar normalmente. –

+0

estoy seguro de que hay una excepción pero la dosis no se arroja al hilo principal – Hiyasat

2

¿Estás seguro de que se emite la excepción? Si un hilo falla con una excepción, toda la aplicación se bloqueará, lo que puede notar utilizando el evento AppDomain.CurrentDomain.UnhandledException (tenga en cuenta que para cuando se disparó el evento, no puede evitar que se finalice su aplicación, pero puede limpiar los recursos y guardar datos críticos: consulte la documentación del evento para obtener más información).

Pero, para citar el accepted answer de la rosca se ha referido a:

Cualquier hilo que emite una excepción de nivel superior indica un gran problema.

Debería intentar registrar la excepción y/o señalar el (los) otro (s) hilo (s) que este hilo ha fallado.

0

Creo que quizás deberías mirar usando la clase BackgroundWorker. Puede suscribirse al evento RunWorkerCompleted y tiene una propiedad Error que contendrá su excepción.

+0

Gracias, pero encontré algo más poderoso en .NET 4 Tarea http://blogs.msdn.com/b/pfxteam/archive/2009/05/31/9674669.aspx – Hiyasat

+0

Gracias por el enlace - Las tareas se ven muy bien, yo no he tenido la oportunidad de verlos aún. – antsyawn

6

Creo que el meollo del asunto es entender que las excepciones que ocurren dentro de un hilo no se pasarán al hilo de llamada para su manejo.

Por ejemplo, supongamos que tiene un método rebelde:

private static void RebelWithoutACause() 
{ 
    throw new NullReferenceException("Can't touch this!"); 
} 

Digamos que se crea un nuevo hilo que llama a este método en su programa, y ​​ser un programador seguro, decide envolver el trabajo en una try/catch bloque:

private static void Main(string[] args) 
{ 
    try 
    { 
     var thread = new Thread(RebelWithoutACause); 
     thread.Start(); 
     thread.Join(); 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine(ex.ToString()); 
    } 
} 

Sin embargo, si ejecuta este en el depurador, se entera de que no se consigue al bloque catch, y en su lugar van a matar el hilo y el depurador se quejan de que se tener una excepción no controlada .

Debe elegir cómo manejar las excepciones, pero el manejo debe realizarse dentro de cada método de entrada de subprocesos. El manejo típico incluye registrar los detalles, notificar a los usuarios a través de la IU y cerrar su aplicación de la forma más elegante posible.

+0

muy buena explicación! – koumides

0

tal vez hacer algo como esto:

const int numThreads = 8; 
    Thread[] threads = new Thread[numThreads]; 
    Exception[] threadsExceptions = new Exception[numThreads]; 
    for (int i = 0; i < numThreads; i++) { 
     threadsExceptions[i] = null; 
     int closureVariableValue = i; 
     ThreadStart command =() => 
     { 
      try 
      { 
       throw new ArgumentException("thread_" + closureVariableValue + "'s exception"); 
      }catch(Exception any) 
      { 
       threadsExceptions[closureVariableValue] = any; 
      } 
     }; 
     threads[i] = new Thread(command); 
     threads[i].Start(); 
    } 
    for(int i = 0; i < numThreads; i++) 
    { 
     threads[i].Join(); 
     if (threadsExceptions[i] != null) 
     { 
      throw threadsExceptions[i]; 
     } 
    } 
Cuestiones relacionadas