How to make an exception to the task that must be observed in the continuation task?

I have a task to perform HttpWebRequestwith

 Task<WebResponse>.Factory.FromAsync(req.BeginGetRespone, req.EndGetResponse)

which obviously could fail with help WebException. For the caller, I want to return Task<HttpResult>where HttpResultis the helper type for encapsulating the response (or not). In this case, the exception 4xx or 5xx is not an exception.

Therefore, I attached two extensions to the query task. One with TaskContinuationOptions OnlyOnRanToCompletion, and another with OnlyOnOnFaulted. And then wrap it all in Task<HttpResult>to get one result, depending on which completion is completed.

Each of the three child tasks (query plus two continuations) is created using the option AttachedToParent.

But when the caller waits for the returned external task, it is thrown AggregateExceptionif the request is not completed.

I want to continue watching with an error WebExceptionso that the client code can just look at the result. Adding Waita continuation of the continuation of the crash, but trying a try-catch around this does not help. Also, the property is not viewed Exception(like the section "Monitoring exceptions using the Task.Exception property" hints here ).

I could set up an event handler UnobservedTaskExceptionfor filtering, but since the event does not offer a direct link to a faulty task, this will most likely interact outside this part of the application and is a case of a sledgehammer to crack a nut.

Task<T>, - " "?

:

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;
}

:

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 , ...)

, , - , .

+5
1

, : . , WebException Response, HttpWebResponse :

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

, .

+3

All Articles