2012-09-18 14 views
5

Al manejar excepciones en tareas TPL, me he encontrado con dos formas de manejar excepciones. La primera captura la excepción dentro de la tarea y lo devuelve en el resultado de este modo:Administración de excepciones de la biblioteca paralela de tareas

var task = Task<Exception>.Factory.StartNew(
    () => 
     { 
      try 
      { 
       // Do Something 

       return null; 
      } 
      catch (System.Exception e) 
      { 
       return e; 
      } 
     }); 

task.ContinueWith(
    r => 
     { 
      if (r.Result != null) 
      { 
       // Handle Exception 
      } 
     }); 

La segunda es la que se muestra en la documentación y supongo que la forma correcta de hacer las cosas:

var task = Task.Factory.StartNew(
    () => 
     { 
      // Do Something 
     }); 
task.ContinueWith(
    r => 
     { 
      if (r.Exception != null) 
      { 
       // Handle Aggregate Exception 
       r.Exception.Handle(y => true); 
      } 
     }); 

Me pregunto si hay algo malo con el primer acercamiento. He recibido excepciones de 'excepción agregada no controlada' de vez en cuando usando esta técnica y me preguntaba cómo podría suceder esto.

Para aclarar, creo que el segundo patrón es el mejor, pero tengo un fragmento de código que hace uso del primer patrón y estoy tratando de averiguar si es necesario volver a factorizar, es decir, si resulta que no todas las excepciones quedarán atrapadas.

+0

Tuve el mismo problema, aunque lo comprobé con task.IsFaulted, encontré que si tenía una excepción durante la tarea, incluso si lo primero que hice fue verificar eso, y lo noté y desistí, todavía causó problemas ... y tengo una excepción que se escapa que no debería tener ... – BugFinder

Respuesta

3

El primer enfoque supone que se generarán excepciones para cada invocación. Si bien esto podría ser cierto, las excepciones no parecen "excepcionales" y huele a un problema de diseño. Si las excepciones no son excepcionales, entonces el resultado no tiene mucho sentido. El otro problema es que si desea un "resultado" (es decir, algo distinto de Exception) no puede porque la única ranura Result se usa para un Exception. Otro problema es que no obtiene volver a lanzar la excepción en el hilo principal (puede hacerlo manualmente) para no obtener la semántica de captura (es decir, está utilizando el método Handle).

El segundo método será mejor entendido por más personas.

+0

Gracias por sus comentarios. Estoy usando este enfoque dentro de un repositorio donde se esperan excepciones (acceso a la base de datos). Si necesito que se devuelva un resultado, tengo una clase RepositoryResult que la tarea puede devolver y contiene el resultado y la excepción. La continuación de tareas es donde se lleva a cabo el manejo de excepciones (es decir, la llamada al servicio de manejo de excepciones). Lo que realmente me pregunto es cómo puedo terminar con una excepción agregada no controlada con el primer enfoque. – user1680766

+0

Entonces, tendría formas inconsistentes de lidiar con excepciones. No es que 'Task' tenga una forma consistente con' Task 'debido a la falta de una propiedad Result, pero ya existe una propiedad' Task.Exception' y 'IsFaulted' ... –

+0

Estoy de acuerdo, el segundo enfoque es el mejor uno. Lamentablemente, he adoptado un código que hace un uso intensivo del primer patrón y ahora necesito decidir si es necesario volver atrás y volver a factorizarlo, de ahí la pregunta de si el primer patrón puede conducir a excepciones agregadas no controladas. – user1680766

Cuestiones relacionadas