2010-02-19 28 views
5

Tôi có một công việc để thực hiện một HttpWebRequest sử dụngLàm thế nào để bắt buộc một ngoại lệ từ một nhiệm vụ được quan sát trong một nhiệm vụ liên tục?

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

mà rõ ràng có thể thất bại với một WebException. Để người gọi tôi muốn trả lại một Task<HttpResult> trong đó HttpResult là loại trình trợ giúp để đóng gói phản hồi (hoặc không). Trong trường hợp này, phản hồi 4xx hoặc 5xx là không phải là ngoại lệ.

Do đó tôi đã đính kèm hai lần tiếp tục vào tác vụ yêu cầu. Một với TaskContinuationOptionsOnlyOnRanToCompletion và một với OnlyOnOnFaulted. Và sau đó bọc toàn bộ thứ trong một Task<HttpResult> để nhận một kết quả mà bất kỳ sự tiếp tục nào hoàn thành.

Mỗi trong ba nhiệm vụ con (yêu cầu cộng với hai lần tiếp tục) được tạo với tùy chọn AttachedToParent.

Nhưng khi người gọi đợi trên nhiệm vụ bên ngoài được trả lại, yêu cầu AggregateException bị ném là yêu cầu không thành công.

Tôi muốn, trong lần tiếp tục bị lỗi, hãy quan sát WebException để mã khách hàng chỉ có thể xem kết quả. Thêm một số Wait trong quá trình tiếp tục phát sinh lỗi, nhưng việc thử bắt xung quanh điều này không giúp ích gì. Cũng không xem xét thuộc tính Exception (như phần "Quan sát ngoại lệ bằng cách sử dụng thuộc tính Task.Exception" gợi ý here).

Tôi có thể cài đặt một bộ xử lý sự kiện UnobservedTaskException để lọc, nhưng khi sự kiện không có liên kết trực tiếp đến tác vụ bị lỗi, điều này có thể tương tác bên ngoài phần này của ứng dụng và là trường hợp của búa tạ.

Với trường hợp có lỗi Task<T> có phương tiện nào gắn cờ nó là "lỗi được xử lý" không?

đang Giản:

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

với:

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 cuối cùng sẽ spin off nhiệm vụ hơn nữa để có được nội dung của các phản ứng ...)

Các khách hàng nên có thể chờ đợi nhiệm vụ và sau đó nhìn vào kết quả của nó, mà không có nó ném do lỗi được mong đợi và đã được xử lý.

+0

'TaskScheduler.UnobservedTaskException' không được kích hoạt, ngay cả khi hầu hết (nếu không phải tất cả) các địa điểm' AggregateException' sẽ bị loại bỏ. – Richard

Trả lời

3

Cuối cùng, tôi lấy con đường đơn giản nhất mà tôi có thể nghĩ đến: ẩn ngoại lệ. Điều này có thể vì WebException có một tài sản Response mà cho phép truy cập đến HttpWebResponse Tôi muốn:

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

Và sau đó xử lý các lỗi, chuyển hướng và phản hồi thành công trong nhiệm vụ tiếp tục.

Các vấn đề liên quan