5

HttpWebRequest使用するタスクがあります

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

これは明らかに。で失敗する可能性がありWebExceptionます。呼び出し元に、応答をカプセル化する(またはカプセル化しない)ヘルパータイプであるTask<HttpResult>whereを返したいと思います。HttpResultこの場合、4xxまたは5xx応答も例外ではありません。

したがって、リクエストタスクに2つの継続を添付しました。1つはでTaskContinuationOptions OnlyOnRanToCompletion、もう1つはOnlyOnOnFaulted。そして、すべてをaでラップして、Task<HttpResult>継続が完了した1つの結果を取得します。

3つの子タスク(要求と2つの継続)のそれぞれは、オプションを使用して作成されAttachedToParentます。

ただし、呼び出し元が返された外部タスクを待機するAggregateExceptionと、要求が失敗した場合にスローされます。

WebException障害が発生した継続で、クライアントコードが結果を確認できるように観察したいと思います。on fault継続スローにを追加しますWaitが、これを回避するためのtry-catchは役に立ちません。また、プロパティを見ることもありませんException「Task.Exceptionプロパティを使用した例外の監視」セクションのヒントとして)。

フィルタリングするイベントハンドラーをインストールすることもできUnobservedTaskExceptionますが、イベントは障害のあるタスクへの直接リンクを提供しないため、これはアプリケーションのこの部分の外部で相互作用する可能性があり、大ハンマーがナットを割る場合です。

障害が発生したインスタンスを考えると、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最終的には、応答の内容を取得するためにさらにタスクをスピンオフします...)

クライアントは、予期され、すでに処理されている障害が原因でタスクがスローされることなく、タスクを待機してからその結果を確認できる必要があります。

4

1 に答える 1

3

結局、私は考えられる最も簡単なルートを取りました:例外を隠す。これが可能なのは、私が欲しいものへのアクセスを提供WebExceptionするプロパティがあるからです。ResponseHttpWebResponse

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

次に、継続タスクでエラー、リダイレクト、および成功応答を処理します。

于 2010-04-19T13:08:33.193 に答える