Как Вынудить Исключение из Задачи Наблюдаться в Задаче Продолжения?

У меня есть задача работать HttpWebRequest использование

 Task.Factory.FromAsync(req.BeginGetRespone, req.EndGetResponse)

который может, очевидно, перестать работать с a WebException. Вызывающей стороне я хочу возвратить a Task где HttpResult тип помощника должен инкапсулировать ответ (или не). В этом случае 4xx или 5xx ответ не является исключением.

Поэтому я присоединил два продолжения к задаче запроса. Один с TaskContinuationOptions OnlyOnRanToCompletion и другой с OnlyOnOnFaulted. И затем перенесенный все это в a Task взять один результат, какой бы ни продолжение завершается.

Каждая из трех дочерних задач (запрос плюс два продолжения) создается с AttachedToParent опция.

Но когда вызывающая сторона ожидает на возвращенной внешней задаче, AggregateException брошен отказавший запрос.

Я хочу, в на неработающем продолжении, наблюдать WebException таким образом, клиентский код может просто посмотреть на результат. Добавление a Wait в на бросках продолжения отказа, но выгоде попытки вокруг этого не помогает. Ни делает взгляд на Exception свойство (поскольку раздел "Observing Exceptions By Using the Task. Exception Property" подсказывает здесь).

Я мог установить a UnobservedTaskException обработчик событий для фильтрации но поскольку событие не предлагает прямой ссылки на неработающую задачу, это будет, вероятно, взаимодействовать вне этой части приложения и является случаем кувалды для взламывания гайки.

Приведенный пример неработающего Task есть ли какое-либо средство установки флага его как "обработанный отказ"?

Упрощенный код:

public static Task Start(Uri url) {
    var webReq = BuildHttpWebRequest(url);
    var result = new HttpResult();
    var taskOuter = Task.Factory.StartNew(() => {
        var tRequest = Task.Factory.FromAsync(
                            webReq.BeginGetResponse,
                            webReq.EndGetResponse,
                            null, TaskCreationOptions.AttachedToParent);
        var tError = tRequest.ContinueWith(
                            t => HandleWebRequestError(t, result),
                            TaskContinuationOptions.AttachedToParent
                            |TaskContinuationOptions.OnlyOnFaulted);
        var tSuccess = tRequest.ContinueWith(
                            t => HandleWebRequestSuccess(t, result),
                            TaskContinuationOptions.AttachedToParent
                            |TaskContinuationOptions.OnlyOnRanToCompletion);
        return result;
    });

    return taskOuter;
}

с:

private static HttpDownloaderResult HandleWebRequestError(
                                        Task 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
задан Richard 19 February 2010 в 12:10
поделиться

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
ответ дан 15 December 2019 в 06:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: