এইচটিটিপিপ্লায়েন্টের সময় শেষ হয়ে গেলে আমি কীভাবে বলতে পারি?


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
আমরা এই বিষয়টিকে গিটহাবের উপরে তুলে ধরতে পারি
টাস্কআউটকে টাস্ক

প্রশ্নের জন্য বিশাল upvote। এছাড়াও ... ইউডাব্লুপিতে কীভাবে এটি করবেন কোনও ধারণা? এর উইন্ডোজ.ওয়েব.এইচটিটিপি.এইচটিটিপি ক্লায়েন্টের টাইমআউট সদস্য নেই। এছাড়াও getAsync পদ্ধতি বাতিলকরণ টোকেন গ্রহণ করে না ...
ডু-ডু-নিউ

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
TaskCanceledExceptionএইচটিটিপি সময়সীমার কারণে হয় এবং না হয় তা আমি কীভাবে বলতে পারি, সরাসরি বাতিল বা অন্য কারণে বলুন?
ইউজারকন্ট্রোল

8
@ ইউজারকন্ট্রোল চেক করুন TaskCanceledException.CancellationToken.IsCancellationRequested। যদি মিথ্যা হয়, আপনি যুক্তিসঙ্গতভাবে নিশ্চিত হতে পারেন যে এটি একটি সময়সীমা ছিল।
টড মেনিয়ার

3
দেখা যাচ্ছে যে, আপনি IsCancellationRequestedআগে যেমন ভেবেছিলেন সরাসরি বাতিল করার ক্ষেত্রে আপনি ব্যতিক্রমটির টোকেন সেট করতে গণনা করতে পারবেন না : stackoverflow.com/q/29319086/62600
টড মেনিয়ার

2
@ টেস্টিং তারা আলাদা আচরণ করে না । এটি কেবলমাত্র আপনার কাছে একটি টোকেন রয়েছে যা ব্যবহারকারী বাতিলকরণের অনুরোধ এবং একটি অভ্যন্তরীণ (আপনার অ্যাক্সেস করতে পারে না এবং আপনার প্রয়োজন হয় না) প্রতিনিধিত্ব করবে যা ক্লায়েন্টের সময়সীমাটি উপস্থাপন করে। এটি ব্যবহারের ক্ষেত্রে পৃথক হয়
স্যার রুফো

59

আমি একই ইস্যুটি পুনরুত্পাদন করছি এবং এটি সত্যিই বিরক্তিকর। আমি এই দরকারী খুঁজে পেয়েছি:

HttpClient - সামগ্রিক ব্যতিক্রমগুলি নিয়ে কাজ করে

এইচটিপিপি্লিয়েন্টে বাগ

লিঙ্কগুলি কোথাও না যাওয়ার ক্ষেত্রে কিছু কোড:

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

আমার অভিজ্ঞতায়, ওয়েবএক্সেপশন কোনও পরিস্থিতিতে ধরা যায় না। অন্যরা কি অন্যরকম কিছু অনুভব করছেন?
ক্রাশ করুন

1
@ ক্রাশ ধরা WebException যেতে পারে সম্ভবত এটি সাহায্য করবে।
ডেভিডআরআর

আমি সিটি ব্যবহার না করলে এটি আমার পক্ষে কাজ করে না। আমি কেবল টাস্কটি ব্যবহার করছি <T> টাস্ক = সামারটাস্ক () চেষ্টা করুন result টি ফলাফল = টাস্ক es ফলাফল} ধরা (টাসক্যান্সেলড এক্সেক্সশন)}} ক্যাচ (ব্যতিক্রম e)} the কেবলমাত্র সাধারণ ব্যতিক্রম ধরা পড়ে, টাস্ক-ক্যান্সেলড এক্সেকশন নয়। আমার কোড সংস্করণে কি ভুল?
নাওমি

1
মূলটি আর্কাইভ ফোরাম পোস্টে প্রদর্শিত হওয়ার পরে আমি একটি নতুন বাগ প্রতিবেদন তৈরি করেছি: কানেক্ট.মাইক্রোসফট
ভিজুয়ালস্টুডিও

1
টোকেন যদি বাইরে থেকে পাস করা হয় তবে এটি default(CancellationToken)তুলনার আগে নয় ex.CancellationToken
সার্জ

25

আমি দেখতে পেয়েছি যে পরিষেবা কলটি শেষ হয়ে গেছে কিনা তা নির্ধারণ করার সর্বোত্তম উপায় হ'ল এইচটিপিপ্লিয়েন্টের সময়সীমা সম্পত্তি নয় একটি বাতিলকরণ টোকেন ব্যবহার করা:

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 থেকে

একটি ডোমেন নেম সিস্টেম (ডিএনএস) কোয়েরি ফিরে আসতে বা সময় শেষ হতে 15 সেকেন্ড সময় নিতে পারে। যদি আপনার অনুরোধটিতে কোনও হোস্টের নাম থাকে যা সমাধানের প্রয়োজন হয় এবং আপনি 15 সেকেন্ডের চেয়ে কম সময়ে একটি মানকে টাইমআউট সেট করেছেন, আপনার অনুরোধের একটি সময়সীমা নির্দেশ করতে কোনও ওয়েবএক্সসেপশন ছুঁড়ে ফেলার আগে এটি 15 সেকেন্ড বা তার বেশি সময় নিতে পারে ।

তারপরে আপনি Statusসম্পত্তিটিতে অ্যাক্সেস পাবেন , ওয়েবএক্সেপশন স্ট্যাটাস দেখুন


3
হুম, আমি AggregateExceptionএকটি TaskCancelledExceptionভিতরে দিয়ে ফিরে আসছি । আমি অবশ্যই কিছু ভুল করছি ...
বেনজল

আপনি ব্যবহার করছেন catch(WebException e)?
ব্যবহারকারী 247702

নাহ, এবং যদি আমি চেষ্টা করি তবে AggregateExceptionতা নিয়ন্ত্রণহীন। আপনি যদি ভিএস কনসোল প্রকল্প তৈরি করেন তবে একটি রেফারেন্স যুক্ত করুন System.Net.Httpএবং কোডটি এতে ফেলে দিন main, আপনি নিজের জন্য (যদি আপনি চান) দেখতে পারেন।
বেনজল

5
যদি অপেক্ষা সময়টি কার্যের সময়সীমা অতিক্রম করে, আপনি একটি পাবেন TaskCanceledException। এটি টিপিএল এর অভ্যন্তরীণ সময়সীমা পরিচালনা দ্বারা ছুঁড়েছে বলে মনে হয়, এর চেয়ে উচ্চতর স্তরে HttpWebClient। সেখানে একটি ভাল উপায় হতে বলে মনে হচ্ছে না সময় পার হয়ে বাতিলের এবং একটি ব্যবহারকারীর বাতিলের মধ্যে পার্থক্য করতে। এর ফলশ্রুতিটি হ'ল আপনি নিজের WebExceptionমধ্যে একটি পেতে পারেন না AggregateException
জেটি

1
অন্যরা যেমন বলেছে, আপনাকে ধরে নিতে হবে টাস্ক ক্যান্সেলড এক্সপশন সময়সীমা শেষ হয়েছিল। আমি চেষ্টা করছি here // কোড এখানে} ক্যাচ (সমষ্টিগত এক্সেপশন ব্যতিক্রম) {যদি (ব্যতিক্রম n অভ্যন্তরীণ এক্সেক্সশনস fঅফটাইপ <টাস্ক ক্যান্সেলড এক্সপেশন> ()। // এখানে হ্যান্ডেল টাইমআউট}}
ভিডেক্স

8

মূলত, আপনাকে OperationCanceledExceptionবাতিল করার টোকেনের অবস্থাটি SendAsync(এবং GetAsync, বা HttpClientআপনি যে কোনও পদ্ধতিতে ব্যবহার করছেন) যাচাই করতে হবে এবং তা পরীক্ষা করতে হবে :

  • যদি এটি বাতিল হয়ে যায় ( IsCancellationRequestedসত্য) তবে এর অর্থ হল অনুরোধটি সত্যই বাতিল করা হয়েছিল
  • যদি তা না হয় তবে এর অর্থ অনুরোধটির সময়সীমা শেষ

অবশ্যই, এটি খুব সুবিধাজনক নয় ... TimeoutExceptionসময়সাপেক্ষীর ক্ষেত্রে একটি গ্রহণ করা ভাল । আমি এখানে একটি কাস্টম এইচটিটিপি বার্তা হ্যান্ডলারের উপর ভিত্তি করে একটি সমাধান প্রস্তাব করছি: এইচটিটিপি ক্লিনেন্টের সাথে আরও ভাল সময়সীমা হ্যান্ডলিং


আহ! এটা তুমি! আমি আজ আপনার ব্লগপোস্টে একটি মন্তব্য লিখেছিলাম। তবে এই উত্তরের প্রতি আকস্মিকভাবে, আমি মনে করি ইসক্যানসেলেশন সম্পর্কিত আপনার মতামতটি সত্য নয়, কারণ মনে হয় এটি আমার পক্ষে সর্বদা সত্য, যখন আমি নিজেই এটি বাতিল করি নি
নোকট করুন

@ ক্নোক্ট এটি অদ্ভুত ... তবে সেক্ষেত্রে আমার ব্লগ পোস্টের সমাধানটি আপনাকে সাহায্য করবে না, কারণ এটিও এর উপর নির্ভর করে
টমাস লেভসেক

1
এই সম্পর্কে গিথুব ইস্যুতে, অনেকেই আমি যা বলেছিলাম তা দাবি করে: যে সময়সীমা শেষ হওয়ার সময় ইসক্যানসেলেশন রিলেকুইস্টড সত্য; সুতরাং আমি আপনার উত্তরটি
নিম্নে লোভে ফেলতে প্রবৃত্ত

@ ননকোস্ট, আমি আপনাকে কী বলব জানি না ... আমি এটি দীর্ঘকাল ধরে ব্যবহার করে আসছি এবং এটি সর্বদা আমার পক্ষে কাজ করে। আপনি কি HttpClient.Timeoutঅসীম সেট করেছেন ?
টমাস লেভেস্ক

না আমি তা করিনি কারণ আমি নিজেই এইচটিপিপ্লিনেন্টকে নিয়ন্ত্রণ করতে পারি না, এটি একটি তৃতীয় পক্ষের লাইব্রেরি যা আমি ব্যবহার করছি
নোকট করুন

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

আমি সাধারণত যা করি তা আমার জন্য বেশ ভাল কাজ করে বলে মনে হয়, প্রক্সি ব্যবহার করার সময় এটি বিশেষত ভাল।


1
আপনি এইভাবে httpclient এর সময়সীমা সেটআপ করেন। এটি প্রশ্নের সমাধান করে না, যখন আপনি কীভাবে বলতেন যে কখন httpclient সময় শেষ হয়ে যায়।
ইথান ফিশার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.