2012-10-01 11 views
24

HttpClient (अर्थात समय समाप्ति http अनुरोध कार्यक्षमता के लिए ओर्थोगोनल माना जा सकता है और इस तरह सामान्य अतुल्यकालिक उपयोगिताओं द्वारा नियंत्रित किया जा सभी अतुल्यकालिक होने के बावजूद, लेकिन यह है कि एक तरफ) अंतर्निहित टाइमआउट सुविधा है और में जब टाइमआउट किक , यह TaskCanceledException फेंक देगा (AggregateException में लपेटा गया है)।उपयोगकर्ता रद्दीकरण से टाइमआउट भेद

टीसीई में CancellationToken है जो CancellationToken.None के बराबर है।

अब अगर मैं अपनी खुद की एक CancellationToken साथ HttpClient प्रदान करते हैं और उपयोग करें कि कार्रवाई को रद्द करने के लिए इससे पहले कि यह खत्म (या समय समाप्त), मैं ठीक उसी TaskCanceledException, फिर एक CancellationToken.None साथ मिलता है।

वहाँ एक समय समाप्ति के अनुरोध को रद्द कि क्या पता लगाने के लिए, बनाने के लिए बिना एकमात्र अपवाद फेंका को देखकर एक तरह से अभी भी है, , मेरे अपने CancellationToken कोड है कि अपवाद की जाँच करता है के लिए सुलभ?

पीएस क्या यह एक बग हो सकता है और CancellationToken किसी भी तरह से CancellationToken.None पर गलत तरीके से तय किया गया है? में कस्टम रद्दीकरण टोकन केस का उपयोग करके रद्द कर दिया गया है, तो मैं उस कस्टम टोकन के बराबर TaskCanceledException.CancellationToken की अपेक्षा करता हूं।

संपादित मूल CancellationTokenSource के उपयोग के साथ, समस्या में थोड़ा और अधिक स्पष्ट करने के लिए, यह समय समाप्ति और उपयोगकर्ता रद्द भेद करने के लिए आसान है:

origCancellationTokenSource.IsCancellationRequested == सच

अपवाद से CancellationToken प्राप्त करना हालांकि गलत जवाब देता है:

((TaskCanceledException) e.InnerException) == झूठी

यहाँ एक न्यूनतम उदाहरण .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

कि यह व्यवहार दिखाता कोड का एक न्यूनतम टुकड़ा पोस्ट करें: (मज़बूती से) टोकन कि अपवाद से जुड़ा हुआ है पर तैयार हो जाओ नहीं। –

+0

कोड क्यों नहीं है जो अपवाद को संभालने वाले कार्य को शुरू करता है?कोड के उस टुकड़े में पहले से ही रद्दीकरण टोकन होना चाहिए, यह उस परिदृश्य को प्रबंधित कर सकता है और फिर अपवाद को फेंक सकता है कि आप टोकनसोर्स –

+1

@ फ्रांसिस्कोनोरीगा के बिना प्राप्त करने के लिए अपने उच्च स्तर की कोशिश/पकड़ ब्लॉक चाहते हैं, कभी-कभी आप कोड को अलग करना चाहते हैं, उदा। इसे पुन: प्रयोज्य बनाने के लिए, और असीमित रूप से निष्पादित कोड में भी। तो आप अलग-अलग स्थानों में अपवाद को समाप्त करते हैं, जहां कोड निष्पादित किया गया है। मैं चारों ओर शामिल सभी राज्यों को पारित नहीं करना चाहता हूं, विशेष रूप से अपवाद के रूप में उस राज्य को प्रदान करने के लिए लगता है जब यह आवश्यक है - सिवाय इसके कि यह काम नहीं करता है जैसा कि मुझे लगता है कि यह माना जाता है। छीनने वाले उदाहरण पर एक नज़र डालें जो मोटे तौर पर दिखाता है कि मैं इसका उपयोग कैसे करता हूं। –

उत्तर

4

हाँ, वे दोनों एक ही अपवाद लौटाते हैं (संभवतः एक टोकन का आंतरिक रूप से टाइमआउट के कारण भी) लेकिन इसे आसानी से यह पता लगाया जा सकता है:

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

       return -2; 
      } 

तो बुनियादी तौर पर अगर आप अपवाद मारा लेकिन अपने टोकन निरस्त न किया हो, अच्छी तरह से यह एक नियमित रूप से http टाइमआउट

+0

मैंने ** केवल मेरे प्रश्न में बोले गए अपवाद पर देखकर ** बनाया और मुझे और अधिक स्पष्ट करने के लिए कुछ और विशिष्टताओं को जोड़ा जो मैं पूछ रहा हूं। –

+0

'ऑपरेशन रद्द किए गए अपवाद' को भी फेंक दिया गया है यदि अनुरोध लंबित होने पर 'HttpClient' का निपटारा किया गया है, या यदि 'HttpClient.CancelPendingRequests' कहा जाता है। इन मामलों को कॉल नियंत्रित करते समय इन मामलों को प्रतिष्ठित किया जा सकता है। – Ernesto

+0

इस उत्तर में विवरण की कमी है ... कहां से 'टोकन' आता है? क्या यह अपवाद की संपत्ति है? डाउनवॉटिंग जब तक आप इसे – ympostor

5

स्वीकार किए जाते हैं जवाब निश्चित रूप से कैसे सिद्धांत में यह चाहिए काम करते हैं, लेकिन दुर्भाग्य से व्यवहार में IsCancellationRequested करता है था

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

+0

आप संलग्न टोकन का उपयोग करने में सक्षम नहीं हो सकते हैं, लेकिन यदि आपके पास मूल टोकन है (जिसे 'SendAsync' पर भेजा गया था), तो आप इसका उपयोग कर सकते हैं। या क्या मैं कुछ न कुछ भूल रहा हूं? –

+0

मुझे लगता है, मुझे याद आ रही है कि प्रश्न केवल अपवाद डेटा पर निर्भर होना आवश्यक है। –

संबंधित मुद्दे