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);
}
कि यह व्यवहार दिखाता कोड का एक न्यूनतम टुकड़ा पोस्ट करें: (मज़बूती से) टोकन कि अपवाद से जुड़ा हुआ है पर तैयार हो जाओ नहीं। –
कोड क्यों नहीं है जो अपवाद को संभालने वाले कार्य को शुरू करता है?कोड के उस टुकड़े में पहले से ही रद्दीकरण टोकन होना चाहिए, यह उस परिदृश्य को प्रबंधित कर सकता है और फिर अपवाद को फेंक सकता है कि आप टोकनसोर्स –
@ फ्रांसिस्कोनोरीगा के बिना प्राप्त करने के लिए अपने उच्च स्तर की कोशिश/पकड़ ब्लॉक चाहते हैं, कभी-कभी आप कोड को अलग करना चाहते हैं, उदा। इसे पुन: प्रयोज्य बनाने के लिए, और असीमित रूप से निष्पादित कोड में भी। तो आप अलग-अलग स्थानों में अपवाद को समाप्त करते हैं, जहां कोड निष्पादित किया गया है। मैं चारों ओर शामिल सभी राज्यों को पारित नहीं करना चाहता हूं, विशेष रूप से अपवाद के रूप में उस राज्य को प्रदान करने के लिए लगता है जब यह आवश्यक है - सिवाय इसके कि यह काम नहीं करता है जैसा कि मुझे लगता है कि यह माना जाता है। छीनने वाले उदाहरण पर एक नज़र डालें जो मोटे तौर पर दिखाता है कि मैं इसका उपयोग कैसे करता हूं। –