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
最終的には、応答の内容を取得するためにさらにタスクをスピンオフします...)
クライアントは、予期され、すでに処理されている障害が原因でタスクがスローされることなく、タスクを待機してからその結果を確認できる必要があります。