tengo una tarea para realizar una HttpWebRequest
usandoCómo forzar una excepción de una tarea para ser observada en una tarea de continuación?
Task<WebResponse>.Factory.FromAsync(req.BeginGetRespone, req.EndGetResponse)
que obviamente puede fallar con un WebException
. Para la persona que llama deseo devolver un Task<HttpResult>
donde HttpResult
es un tipo de ayuda para encapsular la respuesta (o no). En este caso, una respuesta 4xx o 5xx es no una excepción.
Por lo tanto, he adjuntado dos continuaciones a la tarea de solicitud. Uno con TaskContinuationOptions
OnlyOnRanToCompletion
y el otro con OnlyOnOnFaulted
. Y luego envolvió todo el asunto en un Task<HttpResult>
para recoger el resultado que se completa.
Cada una de las tres tareas secundarias (solicitud más dos continuaciones) se crea con la opción AttachedToParent
.
Pero cuando la persona que llama espera en la tarea externa devuelta, se lanza un AggregateException
si la solicitud falla.
Quiero, en la continuación con una falla, observar el WebException
para que el código del cliente pueda ver el resultado. Agregando un Wait
en los lanzamientos de continuación de fallas, pero una prueba de esto no ayuda. Tampoco mira la propiedad Exception
(como la sección "Observando excepciones mediante el uso de la propiedad Task.Exception" insinúa here).
Podría instalar un controlador de eventos UnobservedTaskException
para filtrar, pero como el evento no ofrece un enlace directo a la tarea con errores, probablemente interactúe fuera de esta parte de la aplicación y es un martillo para romper una tuerca.
Dado un caso de una falla Task<T>
¿hay algún medio de marcarlo como "error manejado"?
código simplificado:
public static Task<HttpResult> Start(Uri url) {
var webReq = BuildHttpWebRequest(url);
var result = new HttpResult();
var taskOuter = Task<HttpResult>.Factory.StartNew(() => {
var tRequest = Task<WebResponse>.Factory.FromAsync(
webReq.BeginGetResponse,
webReq.EndGetResponse,
null, TaskCreationOptions.AttachedToParent);
var tError = tRequest.ContinueWith<HttpResult>(
t => HandleWebRequestError(t, result),
TaskContinuationOptions.AttachedToParent
|TaskContinuationOptions.OnlyOnFaulted);
var tSuccess = tRequest.ContinueWith<HttpResult>(
t => HandleWebRequestSuccess(t, result),
TaskContinuationOptions.AttachedToParent
|TaskContinuationOptions.OnlyOnRanToCompletion);
return result;
});
return taskOuter;
}
con:
private static HttpDownloaderResult HandleWebRequestError(
Task<WebResponse> respTask,
HttpResult result) {
Debug.Assert(respTask.Status == TaskStatus.Faulted);
Debug.Assert(respTask.Exception.InnerException is WebException);
// Try and observe the fault: Doesn't help.
try {
respTask.Wait();
} catch (AggregateException e) {
Log("HandleWebRequestError: waiting on antecedent task threw inner: "
+ e.InnerException.Message);
}
// ... populate result with details of the failure for the client ...
return result;
}
(HandleWebRequestSuccess
finalmente escindir otras tareas para obtener el contenido de la respuesta ...)
El cliente debe haber capaz de esperar en la tarea y luego ver su resultado, sin tirar debido a una falla que se espera y ya se manejó.
'TaskScheduler.UnobservedTaskException' no se activa, incluso con la mayoría (si no todos) de los lugares' LanzadoExcepción' sería eliminado. – Richard