এইচটিপিপ্লিয়েন্টে অপেক্ষার সাথে অ্যাসিঙ্ক কলটি আর ফিরে আসে না


96

আমি উইন 8 সিপিতে একটি এক্সএএমএল-ভিত্তিক, C#মেট্রো অ্যাপ্লিকেশনটির ভিতরে থেকে একটি কল করছি ; এই কলটি কেবল একটি ওয়েব পরিষেবাদিকে হিট করে এবং JSON ডেটা ফেরত দেয়।

HttpMessageHandler handler = new HttpClientHandler();

HttpClient httpClient = new HttpClient(handler);
httpClient.BaseAddress = new Uri("http://192.168.1.101/api/");

var result = await httpClient.GetStreamAsync("weeklyplan");
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(WeeklyPlanData[]));
return (WeeklyPlanData[])ser.ReadObject(result);

এটি স্তব্ধ হয়ে যায় awaitতবে HTTP কলটি প্রায় অবিলম্বে ফিরে আসে (ফিডলারের মাধ্যমে নিশ্চিত); এটি যেন awaitউপেক্ষা করা হয় এবং এটি কেবল সেখানে স্তব্ধ থাকে।

আপনি জিজ্ঞাসার আগে - হ্যাঁ - প্রাইভেট নেটওয়ার্কের ক্ষমতা চালু আছে।

কোন ধারণা কেন এই স্তব্ধ হবে?


4
আপনি কিভাবে এই asyncপদ্ধতি কল করছেন ? এটি কি ব্যতিক্রম ছুঁড়ে না?
সুইভ

উত্তর:


138

পরীক্ষা করে দেখুন এই উত্তরটি যা খুবই অনুরূপ হবে বলে মনে হয় আমার প্রশ্নের।

চেষ্টা করার মতো কিছু: ConfigureAwait(false)ফিরে আসা টাস্ককে কল করুন GetStreamAsync()। যেমন

var result = await httpClient.GetStreamAsync("weeklyplan")
                             .ConfigureAwait(continueOnCapturedContext:false);

এটি দরকারী কিনা তা আপনার উপরের কোডটি কীভাবে ডাকা হচ্ছে তার উপর নির্ভর করে - আমার ক্ষেত্রে asyncপদ্ধতিটি কল Task.GetAwaiter().GetResult()করে কোডটি স্থগিত করে।

কারণ GetResult()টাস্ক সম্পূর্ণ না হওয়া অবধি বর্তমান থ্রেডটিকে অবরুদ্ধ করে। যখন টাস্কটি সম্পন্ন হয় তখন এটি থ্রেড প্রসঙ্গে পুনরায় প্রবেশের চেষ্টা করে যেখানে এটি শুরু হয়েছিল তবে তা করতে পারে না কারণ সেই প্রসঙ্গে ইতিমধ্যে একটি থ্রেড রয়েছে, যা কলটিতে GetResult()... ব্লক করে দেওয়া হয়েছে !

এই এমএসডিএন পোস্টটি কীভাবে .NET সমান্তরাল থ্রেডগুলিকে সিঙ্ক্রোনাইজ করে - এবং আমার নিজের প্রশ্নের উত্তরটি কিছু সেরা অনুশীলন দেয় তার কিছুটা বিশদে চলে যায় ।


12
ধন্যবাদ, প্রায় async ছেড়ে দিয়েছেন / এটি দেখার আগে অপেক্ষা করুন।
ডেন

4
আমিও! কেন এই জিনিস ভাল ডকুমেন্টেড হয় না? আবারও ধন্যবাদ
অভ্রোহম ইয়িস্রোয়েল

4
এটি যদি ইউআই প্রসঙ্গে এবং এএসপি.এনইটি প্রসঙ্গে না হয় তবে কি ঘটবে?
মেশিনারিয়াম

4
দুর্দান্ত উত্তর! তবে আমি বিভ্রান্ত হয়ে পড়েছি কেন এখনও পর্যন্ত এই সমস্যাটি কেবল এইচটিপিপিলেয়েন্ট ব্যবহার করার সময় আমার মনে হয়েছে, মনে হচ্ছে এইচটিপিপিলেয়েন্টের অন্তর্নিহিত বাস্তবায়নটি সঠিকভাবে প্রয়োগ করা হয়নি। অন্যান্য থমথমে আমি খুঁজে পেয়েছি যে বর্তমান থ্রেডটি এসটিএ হিসাবে সেট করে যা সাহায্য করে তবে সত্যই অপ্রত্যক্ষ হয় বিশেষত যখন আপনি কোনও তৃতীয় পক্ষের অ্যাসেম্বলি ব্যবহার করছেন এবং জানেন না যে হুডের নীচে কিছু কল অবশ্যই একটি প্রতিক্রিয়ার জন্য অপেক্ষা করবে যে এটি কখনও পেতে যাচ্ছে না। আমার ক্ষেত্রে ডিলটি ইন-হাউস ছিল, সুতরাং আমরা কনফিগার করতে পেরেছিলাম ... তবে এটি HTTPClient আপত্তিতে সর্বনিম্ন স্তরে করতে হয়েছিল।
ক্রিস শ্যাচলার

4
@ChrisSchaller নিশ্চিত করুন এ সম্পূর্ণ উত্তর পড়তে stackoverflow.com/a/10351400/174735 , যা ইস্যু মোটামুটি সম্পূর্ণরূপে ব্যাখ্যা করে।
বেনিয়ামিন ফক্স

5

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


0

দাবি অস্বীকার: আমি কনফিগারআউট () সমাধানটি পছন্দ করি না কারণ আমি এটি স্বজ্ঞাত এবং মনে রাখতে অসুবিধে পাই। পরিবর্তে আমি টাস্কে অ-প্রতীক্ষিত পদ্ধতি কলগুলিকে মোড়ানোর সিদ্ধান্তে পৌঁছেছি un এটি 100% কাজ করে বলে মনে হচ্ছে তবে এটি কেবল রেসের শর্ত হতে পারে !? সৎ হতে কী চলছে তা আমি এতটা নিশ্চিত নই। এই উপসংহারটি ভুল হতে পারে এবং আমি আশা করি মন্তব্যগুলি থেকে শিখতে এখানে আমার স্ট্যাকওভারফ্লো পয়েন্টগুলি ঝুঁকিপূর্ণ করব :- পি। দয়া করে সেগুলি পড়ুন!

আমি শুধু বর্ণনা অনুযায়ী সমস্যা এবং আরো তথ্য পাওয়া এখানে

বিবৃতিটি হ'ল: "আপনি একটি অ্যাসিক্রোনাস পদ্ধতিতে কল করতে পারবেন না"

await asyncmethod2()

একটি পদ্ধতি যা ব্লক করে from

myAsyncMethod().Result

আমার ক্ষেত্রে আমি কলিং পদ্ধতিটি পরিবর্তন করতে পারি নি এবং এটি অ্যাসিঙ্ক ছিল না। তবে আমি আসলে ফলাফলটির বিষয়ে চিন্তা করিনি। যেমনটি আমার মনে আছে এটির ফলাফলটি সরিয়ে ফেলাও কার্যকর হয়নি es ফলাফল এবং অপেক্ষার অনুপস্থিত রয়েছে।

সুতরাং আমি এটি করেছি:

public void Configure()
{
    var data = "my data";
    Task.Run(() => NotifyApi(data));
}

private async Task NotifyApi(bool data)
{
    var toSend = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
    await client.PostAsync("http://...", data);
}

আমার ক্ষেত্রে আমি কলিং নন-অ্যাসিঙ্ক পদ্ধতিতে ফলাফলটির বিষয়ে চিন্তা করিনি তবে আমার ধারণা এই ব্যবহারের ক্ষেত্রে এটি বেশ সাধারণ। কলিং অ্যাসিঙ্ক পদ্ধতিতে আপনি ফলাফলটি ব্যবহার করতে পারেন।

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