2015-03-21 21 views
84

Nó hoạt động tốt khi có một hoặc hai nhiệm vụ tuy nhiên ném một lỗi "Một nhiệm vụ đã bị hủy bỏ" khi chúng tôi có nhiều hơn một nhiệm vụ được liệt kê.HttpClient - Tác vụ đã bị hủy?

enter image description here

List<Task> allTasks = new List<Task>(); 
allTasks.Add(....); 
allTasks.Add(....); 
Task.WaitAll(allTasks.ToArray(), configuration.CancellationToken); 


private static Task<T> HttpClientSendAsync<T>(string url, object data, HttpMethod method, string contentType, CancellationToken token) 
{ 
    HttpRequestMessage httpRequestMessage = new HttpRequestMessage(method, url); 
    HttpClient httpClient = new HttpClient(); 
    httpClient.Timeout = new TimeSpan(Constants.TimeOut); 

    if (data != null) 
    { 
     byte[] byteArray = Encoding.ASCII.GetBytes(Helper.ToJSON(data)); 
     MemoryStream memoryStream = new MemoryStream(byteArray); 
     httpRequestMessage.Content = new StringContent(new StreamReader(memoryStream).ReadToEnd(), Encoding.UTF8, contentType); 
    } 

    return httpClient.SendAsync(httpRequestMessage).ContinueWith(task => 
    { 
     var response = task.Result; 
     return response.Content.ReadAsStringAsync().ContinueWith(stringTask => 
     { 
      var json = stringTask.Result; 
      return Helper.FromJSON<T>(json); 
     }); 
    }).Unwrap(); 
} 
+0

Ngoại lệ nói gì? – RagtimeWilly

+0

Tại sao bạn lấy tham số 'CancellationToken' làm tham số và không sử dụng nó? –

Trả lời

128

Có 2 lý do có khả năng là một TaskCanceledException sẽ được ném ra:

  1. Something gọi Cancel() trên CancellationTokenSource gắn liền với dấu hiệu hủy trước khi nhiệm vụ hoàn thành.
  2. Yêu cầu hết thời gian, tức là không hoàn thành trong khoảng thời gian bạn đã chỉ định trên HttpClient.Timeout.

Tôi đoán là đã hết thời gian chờ. (Nếu đó là một hủy rõ ràng, bạn có lẽ sẽ hiện ra điều đó.) Bạn có thể chắc chắn hơn bằng cách kiểm tra ngoại lệ:

try 
{ 
    var response = task.Result; 
} 
catch (TaskCanceledException ex) 
{ 
    // Check ex.CancellationToken.IsCancellationRequested here. 
    // If false, it's pretty safe to assume it was a timeout. 
} 
+3

Vậy giải pháp có thể là gì? Tôi có một vấn đề tương tự. http://stackoverflow.com/questions/36937328/get-asp-net-mvc5-webapi-token-fails-sometimes?noredirect=1#comment61434357_36937328 –

+20

@Dimi - điều này khá cũ, nhưng giải pháp tôi đã sử dụng là đặt thuộc tính Thời gian chờ cho một giá trị lớn hơn: 'httpClient.Timeout = TimeSpan.FromMinutes (30)' – RQDQ

+1

@RQDQ, bạn là người đàn ông! Không sử dụng constructor đã giải quyết được vấn đề cho tôi. Trong trường hợp cụ thể của tôi, tôi muốn hết thời gian chờ tính bằng mili giây. Sử dụng 'TimeSpan.FromMilliseconds (Configuration.HttpTimeout)' trái với 'TimeSpan mới (Configuration.HttpTimeout)' đã xử lý. Cảm ơn! –

5

Tôi chạy vào vấn đề này bởi vì phương pháp Main() tôi đã không chờ đợi cho các nhiệm vụ để hoàn thành trước khi trở về, do đó, Task<HttpResponseMessage> myTask đã bị hủy khi chương trình bảng điều khiển của tôi bị thoát.

Giải pháp là gọi myTask.GetAwaiter().GetResult() trong Main() (từ this answer).

+0

Cảm ơn rất nhiều, Bạn đã tiết kiệm rất nhiều thời gian của tôi. – RaM

2

Một khả năng khác là kết quả không được chờ đợi ở phía máy khách. Điều này có thể xảy ra nếu bất kỳ phương thức nào trong ngăn xếp cuộc gọi không sử dụng từ khóa chờ đợi để chờ cuộc gọi được hoàn thành.

+0

Cảm ơn Manish, Điều này đã giúp khắc phục ngoại lệ của tôi. – Gunarathinam

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