parallel - task result c#
La(s) excepción(es) de una Tarea no se observaron al Esperar en la Tarea o al acceder a su propiedad de Excepción. Como resultado, la excepción no observada fue (3)
Por supuesto; significa que se finalizó una Task
después de dejarla en la recolección de basura, pero la tarea en sí falló. Hay dos soluciones:
- manejar las tareas fallan directamente (use
ContinueWith(...)
para suscribirse, y marque.IsFaulted
y.Exception
en laTask
en el parámetro) - manejar el evento
TaskScheduler.UnobservedTaskException
y marcarlo observado (llamar ae.SetObserved()
después de registrar el error)
¿Qué significa esto y cómo resolverlo?
Estoy usando tareas TPL.
Todo el error
La (s) excepción (es) de una Tarea no se observaron al Esperar en la Tarea o al acceder a su propiedad de Excepción. Como resultado, la excepción no observada se volvió a lanzar por el hilo del finalizador.
en System.Threading.Tasks.TaskExceptionHolder.Finalize ()
mscorlib
Prueba este:
public static void ThrowFirstExceptionIfHappens(this Task task)
{
task.ContinueWith(t =>
{
var aggException = t.Exception.Flatten();
foreach (var exception in aggException.InnerExceptions)
{
throw exception; // throw only first, search for solution
}
},
TaskContinuationOptions.OnlyOnFaulted); // not valid for multi task continuations
}
public static Task CreateHandledTask(Action action)
{
Task tsk = Task.Factory.StartNew(action);
tsk.ThrowFirstExceptionIfHappens();
return tsk;
}
Si crea una Tarea, y nunca llama a la task.Wait()
o intente recuperar el resultado de una Task<T>
, cuando el recolector de basura recoja la tarea, ésta la derribará durante la finalización. Para obtener más información, consulte la página de MSDN sobre Exception Handling en el TPL .
La mejor opción aquí es "manejar" la excepción. Esto se puede hacer a través de una continuación: puede adjuntar una continuación a la tarea y registrar / tragar / etc. la excepción que ocurra. Esto proporciona una forma limpia de registrar excepciones de tareas, y se puede escribir como un método de extensión simple, es decir:
public static void LogExceptions(this Task task)
{
task.ContinueWith( t =>
{
var aggException = t.Exception.Flatten();
foreach(var exception in aggException.InnerExceptions)
LogException(exception);
},
TaskContinuationOptions.OnlyOnFaulted);
}
Con lo anterior, puede evitar que cualquier tarea cierre la aplicación y la inicie, a través de:
Task.Factory.StartNew( () =>
{
// Do your work...
}).LogExceptions();
Alternativamente, puede suscribirse a TaskScheduler.UnobservedTaskException y manejarlo allí.