2010-02-19 17 views
5

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 TaskContinuationOptionsOnlyOnRanToCompletion 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ó.

+0

'TaskScheduler.UnobservedTaskException' no se activa, incluso con la mayoría (si no todos) de los lugares' LanzadoExcepción' sería eliminado. – Richard

Respuesta

3

Al final tomé la ruta más simple que pude pensar: ocultar la excepción. Esto es posible porque WebException tiene una propiedad Response que da acceso a la HttpWebResponse Quiero:

var requestTask = Task<WebResponse>.Factory.FromAsync(
         webReq.BeginGetResponse, 
         ia => { 
          try { 
          return webReq.EndGetResponse(ia); 
          } catch (WebException exn) { 
          requestState.Log(...); 
          return exn.Response; 
          } 
         }); 

Y entonces controlar los errores, redirecciones y respuestas de éxito en la tarea de continuación.

Cuestiones relacionadas