HttpClient'in zaman aşımına uğradığını nasıl anlayabilirim?


142

Anlayabildiğim kadarıyla, bunun belirli bir zaman aşımı olduğunu bilmenin bir yolu yok. Doğru yere bakmıyor muyum yoksa daha büyük bir şey mi kaçırıyorum?

string baseAddress = "http://localhost:8080/";
var client = new HttpClient() 
{ 
    BaseAddress = new Uri(baseAddress), 
    Timeout = TimeSpan.FromMilliseconds(1) 
};
try
{
    var s = client.GetAsync("").Result;
}
catch(Exception e)
{
    Console.WriteLine(e.Message);
    Console.WriteLine(e.InnerException.Message);
}

Bu döndürür:

Bir veya daha fazla hata oluştu.

Bir görev iptal edildi.



Soru için büyük bir oylama. Ayrıca ... UWP'de bunu nasıl yapacağınız hakkında bir fikriniz var mı? Windows.Web.HTTP.HTTPClient'in zaman aşımı üyesi yok. Ayrıca GetAsync yöntemi iptal jetonunu kabul etmez ...
Do-do-new

1
6 yıl sonra ve bir müşterinin zaman aşımına uğradığını bilmek hala mümkün görünmüyor.
Steve Smith

Yanıtlar:


61

GetAsyncYöntemi beklemeniz gerekiyor . Daha sonra TaskCanceledExceptionzaman aşımına uğradıysa bir atar . Ek olarak GetStringAsyncve GetStreamAsyncdahili olarak zaman aşımını işleyin, böylece ASLA atmazlar.

string baseAddress = "http://localhost:8080/";
var client = new HttpClient() 
{ 
    BaseAddress = new Uri(baseAddress), 
    Timeout = TimeSpan.FromMilliseconds(1) 
};
try
{
    var s = await client.GetAsync();
}
catch(Exception e)
{
    Console.WriteLine(e.Message);
    Console.WriteLine(e.InnerException.Message);
}

2
Bunu test ettim ve benim için GetStreamAsynca attım TaskCanceledException.
Sam

38
TaskCanceledExceptionDoğrudan iptal veya başka bir neden olduğunu söyleyerek HTTP zaman aşımından kaynaklanıp kaynaklanmadığını nasıl anlayabilirim ?
UserControl

8
@UserControl denetimi TaskCanceledException.CancellationToken.IsCancellationRequested. Yanlışsa, bunun bir zaman aşımı olduğundan makul bir şekilde emin olabilirsiniz.
Todd Menier

3
IsCancellationRequestedAnlaşıldığı gibi, daha önce düşündüğüm gibi, istisna doğrudan iptal üzerine belirlemeye güvenemezsiniz : stackoverflow.com/q/29319086/62600
Todd Menier

2
@testing Farklı davranmazlar . Sadece kullanıcı iptal isteğini temsil eden bir jeton ve istemci zaman aşımını temsil eden bir dahili (erişemezsiniz ve ihtiyacınız yoktur) vardır.
Farklı

59

Aynı sorunu yeniden üretiyorum ve bu gerçekten can sıkıcı. Bunları yararlı buldum:

HttpClient - toplu istisnalarla uğraşma

HttpClient.GetAsync hata TaskCanceledException değil WebException atmak gerekir

Bağlantıların hiçbir yere gitmemesi durumunda bazı kodlar:

var c = new HttpClient();
c.Timeout = TimeSpan.FromMilliseconds(10);
var cts = new CancellationTokenSource();
try
{
    var x = await c.GetAsync("http://linqpad.net", cts.Token);  
}
catch(WebException ex)
{
    // handle web exception
}
catch(TaskCanceledException ex)
{
    if(ex.CancellationToken == cts.Token)
    {
        // a real cancellation, triggered by the caller
    }
    else
    {
        // a web request timeout (possibly other things!?)
    }
}

Deneyimlerime göre, WebException hiçbir durumda yakalanamaz. Başkaları farklı bir şey mi yaşıyor?
ezmek

1
@crush WebException yapabilirsiniz yakalanacak. Belki de bu yardımcı olacaktır.
DavidRR

Eğer cts kullanmıyorsam bu benim için işe yaramıyor. Ben sadece Görev <T> görev = SomeTask () deneyin {T sonuç = task.Result} catch (TaskCanceledException) {} catch (Exception e) {} Sadece genel istisna yakalandı, TaskCanceledException değil. Kod sürümümde yanlış olan ne?
Naomi

1
Orijinal raporun arşivlenmiş bir forum yayınında göründüğü için yeni bir hata raporu oluşturdum: connect.microsoft.com/VisualStudio/feedback/details/3141135
StriplingWarrior

1
Jeton dış kontrolden geçirilirse, default(CancellationToken)karşılaştırma yapmadan önce değildir ex.CancellationToken.
SerG

25

Hizmet çağrısı zaman aşımına uğradı olmadığını belirlemek için en iyi yolu HttpClient'ın zaman aşımı özelliği değil bir iptal belirteci kullanmak olduğunu bulundu:

var cts = new CancellationTokenSource();
cts.CancelAfter(timeout);

Ve sonra servis çağrısı sırasında CancellationException'ı işleyin ...

catch(TaskCanceledException)
{
    if(!cts.Token.IsCancellationRequested)
    {
        // Timed Out
    }
    else
    {
        // Cancelled for some other reason
    }
}

Tabii ki zaman aşımı bir şeylerin hizmet tarafında meydana gelirse, bunun bir WebException tarafından işlenmesi gerekir.


1
Hmm, sanırım olumsuzluk operatörü (bir düzenlemeye eklenen) bu örneğin anlamlı olması için kaldırılmalıdır? Eğer cts.Token.IsCancellationRequestedbir true, bir zaman aşımı oluştu anlamına gerekir?
Lasse Christiansen

9

Gönderen http://msdn.microsoft.com/en-us/library/system.net.http.httpclient.timeout.aspx

Bir Etki Alanı Adı Sistemi (DNS) sorgusunun geri dönmesi veya zaman aşımına uğraması 15 saniye sürebilir. İsteğiniz, çözüm gerektiren bir ana bilgisayar adı içeriyorsa ve Zaman Aşımı'nı 15 saniyeden daha az bir değere ayarlarsanız , isteğinizde bir zaman aşımını belirtmek için bir WebException özel durumunun atılması 15 saniye veya daha uzun sürebilir .

Daha sonra Statusözelliğe erişirsiniz , bkz. WebExceptionStatus


3
Hm, içeriden AggregateExceptionbir geri dönüyorum TaskCancelledException. Yanlış bir şey
yapmalıyım

Kullanıyor musunuz catch(WebException e)?
user247702

Hayır, ve eğer denersem, ele AggregateExceptionalınmaz. Bir VS konsolu projesi oluşturursanız, bir başvuru ekleyin System.Net.Httpve kodu içine bırakın, mainkendiniz görebilirsiniz (isterseniz).
Benjol

5
Bekleme süresi görevin zaman aşımı süresini aşarsa, bir TaskCanceledException. Bu, TPL'nin dahili zaman aşımı yönetimi tarafından, daha yüksek bir seviyede atılmış gibi görünüyor HttpWebClient. Orada iyi bir yol görünmüyor bir zaman aşımı iptali ve kullanıcı iptali ayırt etmek. Bunun sonucu, WebExceptioniçinde bir tane alamayabilirsiniz AggregateException.
JT.

1
Diğerlerinin söylediği gibi, TaskCanceledException'ın zaman aşımı olduğunu varsaymanız gerekir. {// Burada kod} catch (AggregateException istisna) {if (exception.InnerExceptions.OfType <TaskCanceledException> () .Any ()) {// Burada zaman aşımı}}
Vdex

8

Temel olarak, yakalamak gerekiyor OperationCanceledExceptionve bu geçildi belirteç iptal durumunu kontrol SendAsync(veya GetAsync, ya da her türlü HttpClientyöntem kullandığınız):

  • iptal edildiğinde ( IsCancellationRequesteddoğruysa), isteğin gerçekten iptal edildiği anlamına gelir
  • değilse, istek zaman aşımına uğradı demektir

Tabii ki, bu çok uygun değil ... TimeoutExceptionzaman aşımı durumunda bir almak daha iyi olurdu . Burada özel bir HTTP ileti işleyicisine dayalı bir çözüm öneriyorum: HttpClient ile daha iyi zaman aşımı yönetimi


Ah! sensin! Bugün daha önce blog yazınıza bir yorum yazdım. Ama bu cevaba göre, IsCancellationRequested ile ilgili fikrinizin doğru olmadığını düşünüyorum, çünkü kendim iptal etmediğim zaman benim için her zaman doğru görünüyor
knocte

@knocte bu garip ... Ama bu durumda, blog gönderimin çözümü size yardımcı olmayacak, çünkü bu da buna bağlı
Thomas Levesque

1
bu konuda github sorunu, birçok söylediklerimi iddia: IsCancellationRequested bir zaman aşımı olduğunda doğrudur; bu yüzden cevabınızı küçümsemeye ayarlıyorum;)
knocte

@knocte, sana ne söyleyeceğimi bilmiyorum ... Bunu uzun zamandır kullanıyorum ve her zaman benim için çalıştı. HttpClient.TimeoutSonsuzluk olarak mı ayarladınız ?
Thomas Levesque

hayır HttpClient'i kendim kontrol edemediğim için kullanmadım, kullandığım üçüncü bir kütüphane, onu kullanan kitap
knocte

-1
_httpClient = new HttpClient(handler) {Timeout = TimeSpan.FromSeconds(5)};

genellikle yaptığım şey, benim için oldukça iyi çalışıyor gibi görünüyor, özellikle vekil kullanırken iyi.


1
Httpclient'in zaman aşımını bu şekilde ayarlarsınız. Bu soruya değinmez, bu da httpclient zaman aşımına uğradığında nasıl anlaşılır.
Ethan Fischer
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.