2012-10-01 33 views
24

HttpClient yerleşik zamanaşımı özelliğine sahiptir (tüm zaman uyumsuz olmalarına rağmen, örneğin zaman aşımları, http isteği işlevine dikey olarak düşünülebilir ve böylece genel asenkronize yardımcı programlar tarafından ele alınabilir, ancak bu bir kenara atılabilir) ve zaman aşımı başladığında TaskCanceledException (AggregateException numaralı ürüne sarılır) atar.Kullanıcı iptali arasındaki zaman aşımını ayırt etme

TCE, CancellationToken.None'a eşit olan CancellationToken içerir. Kendime ait bir CancellationToken ile HttpClient sağlamak ve bittiği (veya zaman aşımına) önce işlemi iptal etmek o kullanırsanız

Şimdi, bir CancellationToken.None ile yine TaskCanceledException aynı olsun.

yapmak zorunda kalmadan, bir zaman aşımı isteğini iptal edip anlamaya, sadece atılan istisna bakarak , hala bir yolu var mı benim kendi CancellationToken istisna denetler koduna erişilebilir?

P.S. Bu bir hata olabilir ve CancellationToken bir şekilde yanlış bir şekilde CancellationToken.None'a ayarlandı mı? Özel CancellationToken kutusunu kullanarak iptal edilen 'da, TaskCanceledException.CancellationToken özel belirtecin eşit olmasını beklerim.

Düzenleme orijinal CancellationTokenSource erişimi olan, sorunu biraz daha açıklığa kavuşturmak için, zaman aşımı ve kullanıcı iptal ayırt etmek kolaydır: gerçek

origCancellationTokenSource.IsCancellationRequested ==

İstisnadan CancellationToken'u almak yanlış yanıt veriyor olsa da:

((TaskCanceledException) e.InnerException) yoğun talep nedeniyle, yanlış ==

İşte minimal örnek .CancellationToken.IsCancellationRequested:

public void foo() 
{ 
    makeRequest().ContinueWith(task => 
    { 
     try 
     { 
      var result = task.Result; 
      // do something with the result; 
     } 
     catch (Exception e) 
     { 
      TaskCanceledException innerException = e.InnerException as TaskCanceledException; 
      bool timedOut = innerException != null && innerException.CancellationToken.IsCancellationRequested == false; 

      // Unfortunately, the above .IsCancellationRequested 
      // is always false, no matter if the request was 
      // cancelled using CancellationTaskSource.Cancel() 
      // or if it timed out 
     } 
    }); 
} 

public Task<HttpResponseMessage> makeRequest() 
{ 
    var cts = new CancellationTokenSource(); 
    HttpClient client = new HttpClient() { Timeout = TimeSpan.FromSeconds(10) }; 
    HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "url"); 

    passCancellationTokenToOtherPartOfTheCode(cts); 
    return client.SendAsync(httpRequestMessage, cts.Token); 
} 
+0

Bu davranışı sergileyen kod minimal bir parça yayınlamak edin: (güvenilir) istisna bağlı belirteci ayarlanır alamadım. –

+0

neden istisnayı işleyen görevi başlatan kod değil?Bu kod parçası zaten CancellationToken'e sahip olmalı, bu senaryoyu yönetebilir ve sadece daha yüksek seviyeli try/catch bloğunun almasını istediğiniz istisnayı TokenSource –

+1

@FranciscoNoriega olmadan alabilirsiniz. Bazen kodu ayırmak, ör. yeniden kullanılabilir hale getirmek için ve ayrıca senkronize olmayan kodda. Böylece, kodun tanımlandığı konumdan farklı yerlerde yakalama istisnalarını sonlandırırsınız. Etrafta yer alan bütün devletleri geçmek zorunda kalmak istemiyorum, özellikle de istisna, gerektiğinde bu durumu sağlıyor gibi görünüyor - dışında olması gerektiği gibi düşünmüyor. Onu nasıl kullandığımı gösteren soyulmuş bir örneğe bakın. –

cevap

4

Evet, onlar her ikisi de aynı istisnayı döndürür (muhtemelen dahili olarak bir belirteci kullanarak zaman aşımı nedeniyle), ancak bunu yaparak kolayca anlaşılabilir:

catch (OperationCanceledException ex) 
      { 
       if (token.IsCancellationRequested) 
       { 
        return -1; 
       } 

       return -2; 
      } 

böylece temelde özel isabet ancak belirteç iptal değilse, iyi o

+0

** Sadece atılan istisnai duruma bakarak ** soruyu boldum ve sorduğum şeyi daha net hale getirmek için biraz daha ayrıntı ekledim. –

+0

"OperationCanceledException", istek beklemede iken "HttpClient" öğesinin atılması durumunda veya "HttpClient.CancelPendingRequests" çağrılırsa atılır. Bu yöntemlere yapılan çağrıları kontrol ederseniz, bu durumlar ayırt edilebilir. – Ernesto

+0

bu cevabın ayrıntıları eksik ... 'token' nereden geliyor? istisna bir özellik midir? – ympostor

5

kabul cevabı kesinlikle maalesef pratikte bu gerektiği teoride çalışır, ancak IsCancellationRequested bu yöntemi kullanıyor düzenli http zaman aşımı oldu

Cancelling an HttpClient Request - Why is TaskCanceledException.CancellationToken.IsCancellationRequested false?

+0

ekli simgeyi kullanamayabilirsiniz, ancak orijinal belirteciniz varsa (bu, SendAsync'e iletildi), bunu kullanabilirsiniz. Yoksa bir şey mi özlüyorum? –

+0

Anladığım kadarıyla, yalnızca istisna verilerine dayanarak sorulması gereken bir soru eksik. –

İlgili konular