কার্যকরভাবে এএসএন.এনইটি ওয়েব এপিআই এর সাথে async / অপেক্ষা করুন


114

আমি async/awaitআমার ওয়েব এপিআই প্রকল্পে ASP.NET এর বৈশিষ্ট্যটি ব্যবহার করার চেষ্টা করছি । এটি আমার ওয়েব এপিআই পরিষেবাদির পারফরম্যান্সে কোনও পার্থক্য আনবে কিনা তা আমি খুব নিশ্চিত নই। আমার অ্যাপ্লিকেশন থেকে কর্মপ্রবাহ এবং নমুনা কোড নীচে সন্ধান করুন।

কর্মধারা:

UI অ্যাপ্লিকেশন → ওয়েব API এন্ডপয়েন্ট (নিয়ন্ত্রণকারী) Web ওয়েব API পরিষেবা স্তরটিতে কল পদ্ধতি another অন্য বাহ্যিক ওয়েব পরিষেবাতে কল করুন → (এখানে আমাদের ডিবি ইন্টারঅ্যাকশন ইত্যাদি রয়েছে)

নিয়ন্ত্রক:

public async Task<IHttpActionResult> GetCountries()
{
    var allCountrys = await CountryDataService.ReturnAllCountries();

    if (allCountrys.Success)
    {
        return Ok(allCountrys.Domain);
    }

    return InternalServerError();
}

পরিষেবা স্তর:

public Task<BackOfficeResponse<List<Country>>> ReturnAllCountries()
{
    var response = _service.Process<List<Country>>(BackOfficeEndpoint.CountryEndpoint, "returnCountries");

    return Task.FromResult(response);
}

আমি উপরের কোডটি পরীক্ষা করেছি এবং কাজ করছি। তবে এটির সঠিক ব্যবহার কিনা তা আমি নিশ্চিত নই async/await। আপনার চিন্তা শেয়ার করুন।


উত্তর:


202

এটি আমার এপিআই এর সম্পাদনায় কোনও পার্থক্য আনবে কিনা তা আমি খুব নিশ্চিত নই।

মনে রাখবেন যে সার্ভার সাইডে অ্যাসিঙ্ক্রোনাস কোডের প্রাথমিক সুবিধাটি স্কেলাবিলিটি । এটি আপনার অনুরোধগুলিকে দ্রুত চালাতে সক্ষম করবে না। আমি এএসপি.নেট সম্পর্কিতasync আমার নিবন্ধেasync বেশ কয়েকটি "আমার ব্যবহার করা উচিত " বিবেচনাগুলি কভার করি ।

আমি মনে করি আপনার ব্যবহারের কেস (অন্যান্য এপিআইগুলিকে কল করা) অ্যাসিঙ্ক্রোনাস কোডের জন্য উপযুক্ত suited সর্বোত্তম পন্থাটি হ'ল প্রথমে আপনার ইউআইকে প্রতিক্রিয়াশীল এবং অ্যাসিনক্রোনাস করা; এটি আপনার অ্যাপ্লিকেশনটি কিছুটা ধীর গতির হলেও দ্রুত বোধ করবে ।

কোড যতদূর যায়, এটি অ্যাসিনক্রোনাস নয়:

public Task<BackOfficeResponse<List<Country>>> ReturnAllCountries()
{
  var response = _service.Process<List<Country>>(BackOfficeEndpoint.CountryEndpoint, "returnCountries");
  return Task.FromResult(response);
}

এর স্কেলিবিলিটি সুবিধাগুলি পেতে আপনার সত্যিকারের একটি অ্যাসিনক্রোনাস বাস্তবায়ন দরকার async:

public async Task<BackOfficeResponse<List<Country>>> ReturnAllCountriesAsync()
{
  return await _service.ProcessAsync<List<Country>>(BackOfficeEndpoint.CountryEndpoint, "returnCountries");
}

বা (যদি এই পদ্ধতিতে আপনার যুক্তি সত্যিই কেবল একটি পাস-থ্রো) হয়:

public Task<BackOfficeResponse<List<Country>>> ReturnAllCountriesAsync()
{
  return _service.ProcessAsync<List<Country>>(BackOfficeEndpoint.CountryEndpoint, "returnCountries");
}

মনে রাখবেন যে "বাইরের ইন" এর চেয়ে "অভ্যন্তরীণ" থেকে কাজ করা আরও সহজ। অন্য কথায়, একটি অ্যাসিনক্রোনাস কন্ট্রোলার অ্যাকশন দিয়ে শুরু করবেন না এবং তারপরে ডাউনস্ট্রিম পদ্ধতিগুলিকে অ্যাসিনক্রোনাস হতে বাধ্য করুন। পরিবর্তে, প্রাকৃতিকভাবে অ্যাসিনক্রোনাস অপারেশনগুলি (বাহ্যিক এপিআই, ডাটাবেস কোয়েরি ইত্যাদি কল করে) সনাক্ত করুন এবং সেগুলি প্রথমে নিম্ন স্তরে অ্যাসিনক্রোনাস করুন ( Service.ProcessAsync)। তারপরে asyncআপনার কন্ট্রোলার ক্রিয়াকে শেষ পদক্ষেপ হিসাবে অবিচ্ছিন্ন করে তুলুন।

এবং কোনও পরিস্থিতিতে আপনার Task.Runএই দৃশ্যে ব্যবহার করা উচিত নয় ।


4
আপনার মূল্যবান মন্তব্যের জন্য স্টিফেনকে ধন্যবাদ। আমি আমার সমস্ত পরিষেবা স্তর পদ্ধতিগুলিকে অ্যাসিঙ্ক হিসাবে পরিবর্তিত করেছি এবং এখন আমি এক্সিকিউটিটাস্ক্যাসেন্স পদ্ধতি ব্যবহার করে আমার বাহ্যিক আরএসটি কল কল করি এবং প্রত্যাশা অনুযায়ী কাজ করছি। অ্যাসিঙ্ক এবং কার্যাদি সম্পর্কে আপনার ব্লগ পোস্টগুলির জন্য ধন্যবাদ। এটি প্রাথমিক ধারণা পেতে সত্যিই আমাকে অনেক সাহায্য করেছিল।
আরপ

5
আপনি এখানে কীভাবে টাস্কটি ব্যবহার করবেন না তা ব্যাখ্যা করতে পারেন?
মার্টেন

1
@ মার্টেন: আমি যে নিবন্ধটি লিঙ্ক করেছি তাতে এটি (সংক্ষেপে) ব্যাখ্যা করি । আমি আমার ব্লগে আরও বিশদ ।
স্টিফেন ক্লিয়ারি

আমি আপনার নিবন্ধটি পড়েছি স্টিফেন এবং মনে হয় এটির কিছু উল্লেখ করা এড়ানো হবে। যখন কোনও এএসপি.এনইটি অনুরোধ উপস্থিত হয় এবং শুরু হয় তখন এটি থ্রেড পুলের থ্রেডে চলছে, ঠিক আছে। তবে যদি এটি অ্যাসিঙ্ক হয়ে যায় তবে হ্যাঁ এটি অ্যাসিঙ্ক প্রক্রিয়াজাতকরণ শুরু করে এবং সেই থ্রেডটি এখনই পুলটিতে ফিরে আসে। তবে async পদ্ধতিতে সম্পাদিত কাজটি নিজেই একটি থ্রেড পুলের থ্রেডে চালিত হবে!
হিউ


12

এটি সঠিক, তবে সম্ভবত কার্যকর নয়।

অপেক্ষার মতো কিছুই নেই - এমনকী এপিআইগুলিকে ব্লক করার জন্য কোনও কল নেই যা অবিচ্ছিন্নভাবে পরিচালনা করতে পারে - তারপরে আপনি অ্যাসিনক্রোনাস অপারেশন (যার ওভারহেড রয়েছে) ট্র্যাক করার জন্য কাঠামো স্থাপন করছেন কিন্তু তারপরে সেই ক্ষমতাটি ব্যবহার করছেন না।

উদাহরণস্বরূপ, যদি পরিষেবা স্তরটি অ্যাসিঙ্ক্রোনাস কলগুলিকে সমর্থন করে এমন সত্তা ফ্রেমওয়ার্কের সাথে ডিবি ক্রিয়াকলাপ সম্পাদন করে:

public Task<BackOfficeResponse<List<Country>>> ReturnAllCountries()
{
    using (db = myDBContext.Get()) {
      var list = await db.Countries.Where(condition).ToListAsync();

       return list;
    }
}

ডিবি জিজ্ঞাসা করা অবস্থায় আপনি শ্রমিক থ্রেডকে অন্য কিছু করার অনুমতি দিতেন (এবং এইভাবে অন্য কোনও অনুরোধটি প্রক্রিয়া করতে সক্ষম)।

অ্যাওয়েট এমন কিছু বিষয় হয়ে থাকে যা পুরোপুরি নেমে যেতে পারে: একটি বিদ্যমান সিস্টেমে বিপরীতমুখী হওয়া খুব কঠিন।


-1

আপনি অ্যাসিঙ্কটি লাভ করছেন না / কার্যকরভাবে অপেক্ষা করছেন কারণ সিঙ্ক্রোনাস পদ্ধতি কার্যকর করার সময় অনুরোধের থ্রেডটি ব্লক করা হবেReturnAllCountries()

অনুরোধটি পরিচালনা করার জন্য যে থ্রেড বরাদ্দ করা হয়েছে ReturnAllCountries()এটি কাজ করার সময় অলসভাবে অপেক্ষা করবে ।

আপনি যদি ReturnAllCountries()অ্যাসিক্রোনাস হতে বাস্তবায়ন করতে পারেন তবে আপনি স্কেলাবিলিটি সুবিধাগুলি দেখতে পাবেন। এর কারণ এটি ReturnAllCountries()কার্যকর করা হচ্ছে এমন সময় অন্য অনুরোধটি পরিচালনা করার জন্য .NET থ্রেড পুলে থ্রেডটি ছেড়ে দেওয়া যেতে পারে । থ্রেডগুলি আরও দক্ষতার সাথে ব্যবহার করে এটি আপনার পরিষেবাকে উচ্চতর থ্রুপুট পাওয়ার অনুমতি দেবে।


এটি সত্য নয়। সকেট সংযুক্ত আছে তবে থ্রেড অনুরোধটি প্রক্রিয়াকরণ অন্য কিছু করতে পারে যেমন কোনও পরিষেবা কলের জন্য অপেক্ষা করার সময় কোনও ভিন্ন অনুরোধ প্রক্রিয়া করা।
গার গডফ্রে

-8

আমি আপনার পরিষেবা স্তরটি এতে পরিবর্তন করব:

public Task<BackOfficeResponse<List<Country>>> ReturnAllCountries()
{
    return Task.Run(() =>
    {
        return _service.Process<List<Country>>(BackOfficeEndpoint.CountryEndpoint, "returnCountries");
    }      
}

যেমনটি আপনার কাছে রয়েছে, আপনি এখনও নিজের _service.Processকলটি সিঙ্ক্রোনসিভভাবে চালিয়ে যাচ্ছেন , এবং এর অপেক্ষায় খুব কম বা কোনও লাভ পাচ্ছেন না।

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


3
ব্লগের লিঙ্ক অনুসারে , আমি দেখতে পেতাম যে আমরা যদি টাস্কটি ব্যবহার করি? তবে কী পদ্ধতিটি এখনও সুসংগতভাবে চালিত হয়?
Arp

হুম। উপরের কোড এবং সেই লিঙ্কের মধ্যে প্রচুর পার্থক্য রয়েছে। আপনার Serviceকোনও অ্যাসিঙ্ক পদ্ধতি নয়, এবং Serviceকলটির মধ্যেই অপেক্ষা করা হচ্ছে না । আমি তার বক্তব্যটি বুঝতে পারি, তবে আমি বিশ্বাস করি না এটি এখানে প্রযোজ্য।
জোনেসোপলিস

8
Task.Runএএসপি.এনইটি এড়ানো উচিত। এই পদ্ধতির async/ থেকে সমস্ত সুবিধাগুলি সরিয়ে ফেলবে awaitএবং প্রকৃতপক্ষে কেবলমাত্র একটি সিঙ্ক্রোনাস কলের চেয়ে লোডের অধীনে আরও খারাপ সম্পাদন করবে।
স্টিফেন ক্লিয়ারি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.