जब HttpClient का समय समाप्त हो गया है तो मैं कैसे बता सकता हूं?


142

जहां तक ​​मैं बता सकता हूं, यह जानने का कोई तरीका नहीं है कि यह विशेष रूप से एक टाइमआउट है जो हुआ है। क्या मैं सही जगह नहीं देख रहा हूँ, या मैं कुछ बड़ा याद कर रहा हूँ?

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

यह रिटर्न:

एक या अधिक त्रुटि हुई।

एक कार्य रद्द कर दिया गया था।


3
हम GitHub पर इस मुद्दे को आगे बढ़ा सकते हैं
csrowell

प्रश्न के लिए विशाल उत्थान। इसके अलावा ... किसी भी विचार कैसे UWP पर यह करने के लिए? इसका Windows.Web.HTTP.HTTPClient में टाइमआउट सदस्य नहीं है। इसके अलावा GetAsync विधि रद्द करने के टोकन को स्वीकार नहीं करती ...
Do-do-new

1
6 साल बाद, और अभी भी यह जानना संभव नहीं है कि क्या कोई ग्राहक समयबद्ध है।
स्टीव स्मिथ

जवाबों:


61

आपको GetAsyncविधि का इंतजार करने की आवश्यकता है । TaskCanceledExceptionयदि यह समय समाप्त हो गया है तो यह फेंक देगा । इसके अतिरिक्त, GetStringAsyncऔर GetStreamAsyncआंतरिक रूप से टाइमआउट संभालते हैं, इसलिए वे कभी भी नहीं फेंकेंगे।

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
मैंने यह परीक्षण किया, और मेरे लिए GetStreamAsyncफेंक दिया TaskCanceledException
सैम

38
मैं यह कैसे बता सकता हूं कि क्या TaskCanceledExceptionHTTP टाइमआउट के कारण होता है और क्या नहीं, सीधे रद्द करने या अन्य कारण कहेंगे?
UserControl 5

8
@UserControl जाँच TaskCanceledException.CancellationToken.IsCancellationRequested। यदि असत्य है, तो आप निश्चित रूप से निश्चित हो सकते हैं कि यह एक समयबाह्य था।
टोड मेनियर

3
जैसा कि यह पता चला है, आप IsCancellationRequestedसीधे रद्द करने पर अपवाद के टोकन पर सेट होने पर भरोसा नहीं कर सकते हैं जैसा कि मैंने पहले सोचा था: stackoverflow.com/q/29319086/62600
टोड मेनियर

2
@testing वे अलग व्यवहार नहीं करते । यह सिर्फ इतना है कि आपके पास एक टोकन है जो उपयोगकर्ता रद्दीकरण अनुरोध और एक आंतरिक (आप एक्सेस नहीं कर सकते हैं और आपको ज़रूरत नहीं है) का प्रतिनिधित्व करेंगे जो क्लाइंट टाइमआउट का प्रतिनिधित्व करता है। यह उपयोग का मामला है जो अलग है
सर रूफो

59

मैं एक ही मुद्दे को पुन: पेश कर रहा हूं और यह वास्तव में कष्टप्रद है। मैं इन उपयोगी पाया है:

HttpClient - कुल अपवादों से निपटना

बग को HttpClient.GetAsync में WebException को फेंकना चाहिए, न कि TaskCanceledException को

लिंक के मामले में कुछ कोड कहीं नहीं जाते हैं:

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!?)
    }
}

मेरे अनुभव में, WebException को किसी भी परिस्थिति में नहीं पकड़ा जा सकता है। क्या अन्य कुछ अलग अनुभव कर रहे हैं?
क्रश करें

1
@ क्रश पकड़ा WebException जा सकता है। शायद इससे मदद मिलेगी।
डेविड आरआर

अगर मैं cts का उपयोग नहीं कर रहा हूं तो यह मेरे लिए काम नहीं करता है। मैं सिर्फ टास्क <T> टास्क = SomeTask () try {T result = task.Result} catch (TaskCanceledException) {} कैच (अपवाद e) {} का उपयोग कर रहा हूं, केवल सामान्य अपवाद पकड़ा गया है, TaskCanceledException नहीं। मेरे कोड के संस्करण में क्या गलत है?
नाओमी

1
मैंने एक नई बग रिपोर्ट बनाई क्योंकि मूल एक संग्रहीत फोरम पोस्ट में दिखाई देता है: Connect.microsoft.com/VisualStudio/feedback/details/3141135
स्ट्रिपिंगवर्कर

1
यदि टोकन को बाहर की जाँच से पास किया गया है तो इसकी default(CancellationToken)तुलना करने से पहले नहीं है ex.CancellationToken
सर्ग

25

मैंने पाया कि सेवा कॉल का समय समाप्त हो गया है या नहीं, यह निर्धारित करने का सबसे अच्छा तरीका कैंसलेशन टोकन का उपयोग करना है न कि HttpClient की टाइमआउट प्रॉपर्टी:

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

और फिर सेवा कॉल के दौरान रद्दीकरण अपवाद को संभालें ...

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

बेशक अगर टाइमआउट चीजों की सेवा की ओर होता है, जो एक वेबएक्ससेप्शन द्वारा नियंत्रित किया जाना चाहिए।


1
हम्म, मुझे लगता है कि इस नमूने के लिए नेगेटिव ऑपरेटर (जिसे एडिट में जोड़ा गया था) को हटा दिया जाना चाहिए? अगर cts.Token.IsCancellationRequestedहै trueतो इसका मतलब यह होगा कि एक समय समाप्त हुआ है?
लासे क्रिश्चियन

9

से http://msdn.microsoft.com/en-us/library/system.net.http.httpclient.timeout.aspx

एक डोमेन नेम सिस्टम (DNS) क्वेरी को वापस लौटने या समय निकालने में 15 सेकंड तक का समय लग सकता है। यदि आपके अनुरोध में एक होस्ट नाम है, जिसमें रिज़ॉल्यूशन की आवश्यकता है और आपने टाइमआउट को 15 सेकंड से कम समय में सेट किया है, तो आपके अनुरोध पर टाइमआउट का संकेत देने के लिए WebException को फेंकने से पहले इसे 15 सेकंड या उससे अधिक समय लग सकता है ।

आप तब Statusसंपत्ति तक पहुँच प्राप्त करते हैं, WebExceptionStatus देखें


3
हम्म, मैं AggregateExceptionएक TaskCancelledExceptionअंदर से वापस आ रहा हूं । मुझे कुछ गलत करना चाहिए ...
बेंजोल

क्या आप उपयोग कर रहे हैं catch(WebException e)?
user247702

नहींं, और अगर मैं कोशिश करता हूं, तो AggregateExceptionवह अनहेल्दी है। यदि आप VS कंसोल प्रोजेक्ट बनाते हैं, तो एक संदर्भ जोड़ें System.Net.Httpऔर कोड को ड्रॉप करें main, आप अपने लिए देख सकते हैं (यदि आप चाहते हैं)।
बेंजोल

5
यदि प्रतीक्षा अवधि कार्य की समयावधि अवधि से अधिक है, तो आपको मिल जाएगा TaskCanceledException। ऐसा लगता है कि TPL के आंतरिक टाइमआउट हैंडलिंग द्वारा, उच्च स्तर से फेंका गया है HttpWebClient। वहाँ एक अच्छा तरीका हो प्रतीत नहीं होता है समय समाप्त रद्द करने और एक उपयोगकर्ता रद्द बीच अंतर करना। इसका कारण यह है कि आप WebExceptionअपने भीतर नहीं मिल सकते हैं AggregateException
जेटी।

1
जैसा कि दूसरों ने कहा है, आपको यह मानकर चलना होगा कि टास्ककैन्लेड ​​अपवाद था टाइमआउट। मैं कोशिश कर रहा हूं {// कोड यहां} कैच (एग्रीगेटएक्स अपवाद अपवाद) {if (अपवाद ।InnerException.OfType <TaskCanceledException> ()। कोई भी ()) {// हैंडल टाइमआउट यहां}}}
Vdex

8

असल में, आप को पकड़ने की जरूरत है OperationCanceledException उस रद्दीकरण टोकन की स्थिति और जांचने की जो SendAsync(या GetAsync, या जो भी HttpClientविधि का उपयोग कर रहा था):

  • यदि इसे रद्द कर दिया गया ( IsCancellationRequestedयह सच है), इसका मतलब है कि अनुरोध वास्तव में रद्द कर दिया गया था
  • यदि नहीं, तो इसका मतलब है कि अनुरोध का समय समाप्त हो गया है

बेशक, यह बहुत सुविधाजनक नहीं है ... TimeoutExceptionटाइमआउट के मामले में इसे प्राप्त करना बेहतर होगा । मैं एक कस्टम HTTP संदेश हैंडलर के आधार पर यहां एक समाधान प्रस्तावित करता हूं: HttpClient के साथ बेहतर टाइमआउट हैंडलिंग


आह! ये तुम हो! मैंने आज से पहले आपके ब्लॉगपोस्ट में एक टिप्पणी लिखी थी। लेकिन इस जवाब के लिए, मुझे लगता है कि IsCancellationRequested के बारे में आपकी बात सच नहीं है, क्योंकि ऐसा लगता है कि यह मेरे लिए हमेशा सच है, जब मैंने इसे खुद रद्द नहीं किया
knocte

@knocte यह अजीब है ... लेकिन उस मामले में, मेरे ब्लॉग पोस्ट से समाधान आपकी मदद नहीं करेगा, क्योंकि यह भी इस पर निर्भर करता है
थॉमस Levesque

1
इस बारे में गितुब मुद्दे में, कई लोगों ने दावा किया कि मैंने क्या कहा है: जब कोई समय समाप्त होता है तो IsCancellationRequested सच है; इसलिए मैं आपके जवाब को कम करने के लिए
लुभा

@knocte, मुझे नहीं पता कि आपको क्या बताना है ... मैं लंबे समय से इसका उपयोग कर रहा हूं और यह हमेशा मेरे लिए काम करता है। क्या आपने HttpClient.Timeoutअनंत को स्थापित किया ?
थॉमस लेवेस्क

नहीं, क्योंकि मैंने अपने आप को HttpClient पर नियंत्रण नहीं किया, इसलिए यह एक तीसरी लाइब्रेरी है जिसका मैं उपयोग कर रहा हूं, जो इसका उपयोग करता है
knocte

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

जो मैं आमतौर पर करता हूं, वह मेरे लिए बहुत अच्छा काम करता है, विशेषकर प्रॉक्सिस का उपयोग करते समय।


1
यह है कि आप httpclient के टाइमआउट को कैसे सेटअप करते हैं। यह प्रश्न को संबोधित नहीं करता है, कि आप कैसे बताएंगे जब httpclient समय समाप्त हो गया है।
एथन फिशर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.