আমি কেন সিঙ্কগুলির পরিবর্তে অ্যাসিঙ্ক ওয়েবএপিআই ক্রিয়াকলাপ তৈরি করব?


109

আমার তৈরি একটি ওয়েব এপিআইতে আমার নিম্নলিখিত অপারেশন রয়েছে:

// GET api/<controller>
[HttpGet]
[Route("pharmacies/{pharmacyId}/page/{page}/{filter?}")]
public CartTotalsDTO GetProductsWithHistory(Guid pharmacyId, int page, string filter = null ,[FromUri] bool refresh = false)
{
    return delegateHelper.GetProductsWithHistory(CustomerContext.Current.GetContactById(pharmacyId), refresh);
}

এই ওয়েবসার্ভিসে কলটি একটি জ্যাকুরি অ্যাজাক্স কলের মাধ্যমে করা হয়েছে:

$.ajax({
      url: "/api/products/pharmacies/<%# Farmacia.PrimaryKeyId.Value.ToString() %>/page/" + vm.currentPage() + "/" + filter,
      type: "GET",
      dataType: "json",
      success: function (result) {
          vm.items([]);
          var data = result.Products;
          vm.totalUnits(result.TotalUnits);
      }          
  });

আমি এমন কিছু বিকাশকারীকে দেখেছি যারা পূর্ববর্তী ক্রিয়াকলাপটি এভাবে প্রয়োগ করে:

// GET api/<controller>
[HttpGet]
[Route("pharmacies/{pharmacyId}/page/{page}/{filter?}")]
public async Task<CartTotalsDTO> GetProductsWithHistory(Guid pharmacyId, int page, string filter = null ,[FromUri] bool refresh = false)
{
    return await Task.Factory.StartNew(() => delegateHelper.GetProductsWithHistory(CustomerContext.Current.GetContactById(pharmacyId), refresh));
}

যদিও বলতে হবে যে গেটপ্রডাক্টস উইথ হিস্টোরি () বেশ দীর্ঘ অপারেশন। আমার সমস্যা এবং প্রসঙ্গটি দেওয়া, কীভাবে ওয়েবএপিআইআই অপারেশনটি অ্যাসিঙ্ক্রোনাস আমাকে উপকৃত করবে?


1
ক্লায়েন্ট পক্ষ এজেএক্স ব্যবহার করে যা ইতিমধ্যে অ্যাসিনক্রোনাস। আপনার যেমন সেবার প্রয়োজন তেমন লেখার দরকার নেই async Task<T>। মনে রাখবেন, টিপিএল এমনকি অস্তিত্বের আগেই
এজেএক্স

65
আপনার কেন বুঝতে হবে আপনি কেন অ্যাসিঙ্ক কন্ট্রোলার প্রয়োগ করছেন, অনেকে তা করেন না। আইআইএসের সীমিত সংখ্যক থ্রেড উপলব্ধ রয়েছে এবং যখন সমস্ত সার্ভার ব্যবহার করা হয় তখন নতুন অনুরোধগুলি প্রক্রিয়া করতে পারে না। অ্যাসিঙ্ক কন্ট্রোলারগুলির সাথে যখন কোনও প্রক্রিয়া I / O শেষ হওয়ার অপেক্ষায় থাকে তখন অন্যান্য থেরাপি প্রক্রিয়াকরণের জন্য সার্ভারের জন্য এটির থ্রেড মুক্ত হয়।
মাটিজা গ্রিক

3
আপনি কি বিকাশকারীরা এটি করতে দেখেছেন? যদি কোনও ব্লগ পোস্ট বা নিবন্ধ থাকে যা সেই কৌশলটির প্রস্তাব দেয় তবে দয়া করে একটি লিঙ্ক পোস্ট করুন।
স্টিফেন ক্লিয়ারি

3
আপনি কেবলমাত্র অ্যাসিঙ্কের সম্পূর্ণ উপকার পাবেন যদি আপনার প্রক্রিয়াটি শীর্ষস্থান থেকে অ্যাসিঙ্ক-সচেতন থাকে (ওয়েব অ্যাপ্লিকেশন নিজেই এবং আপনার নিয়ন্ত্রণকারীরা সহ) আপনার প্রক্রিয়াটির বাইরে যে কোনও অপ্রয়োজনীয় ক্রিয়াকলাপ (টাইমার বিলম্ব, ফাইল আই / ও, ডিবি অ্যাক্সেস সহ, এবং এটি ওয়েব অনুরোধগুলি করে)। এই ক্ষেত্রে, আপনার প্রতিনিধি সহায়তার GetProductsWithHistoryAsync()ফিরে আসা দরকার Task<CartTotalsDTO>। আপনার কন্ট্রোলার অ্যাসিঙ্কটি লেখার কোনও সুবিধা থাকতে পারে যদি আপনি কলগুলিও অ্যাসিঙ্ক হিসাবে স্থানান্তরিত করতে চান তবে; তারপরে আপনি বাকী স্থানান্তরিত হওয়ার সাথে সাথে আপনি async অংশগুলি থেকে সুবিধা পেতে শুরু করুন।
কিথ রবার্টসন

1
আপনার করা প্রক্রিয়াটি যদি বন্ধ হয়ে যায় এবং ডাটাবেসটিকে আঘাত করে তবে আপনার ওয়েব থ্রেডটি ফিরে আসার অপেক্ষা রাখে এবং সেই থ্রেডটি ধরে রাখে। আপনি যদি আপনার সর্বাধিক থ্রেড গণনাটিতে আঘাত করে থাকেন এবং অন্য একটি অনুরোধ আসে তবে এটি অপেক্ষা করতে হবে। কেন যে? পরিবর্তে আপনি সেই থ্রেডটি আপনার নিয়ামক থেকে মুক্ত করতে চাইবেন যাতে অন্য একটি অনুরোধ এটি ব্যবহার করতে পারে এবং যখন ডাটাবেস থেকে আপনার মূল অনুরোধ ফিরে আসে কেবল তখনই অন্য একটি ওয়েব থ্রেড গ্রহণ করতে পারে। msdn.microsoft.com/en-us/magazine/dn802603.aspx
ব্যবহারকারী 441521

উত্তর:


98

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

"সিঙ্ক ওভার সিঙ্ক" সম্পর্কে আমার আলোচনায় আমি দৃ strongly়তার সাথে পরামর্শ দিয়েছিলাম যে আপনার যদি এমন একটি এপিআই থাকে যা অভ্যন্তরীণভাবে সিঙ্ক্রোনালি কার্যকরভাবে প্রয়োগ করা হয় তবে আপনার এমন একটি অ্যাসিনক্রোনাস কাউন্টার পার্ট প্রকাশ করা উচিত নয় যা কেবলমাত্র সিঙ্ক্রোনাস পদ্ধতিতে মোড়কে দেয় Task.Run

থেকে বলা উচিৎ? অ্যাসিঙ্ক্রোনাস পদ্ধতি জন্য সমলয় চাদরে এক্সপোজ?

তবে ওয়েবএপিআই কল করার সময় asyncযেখানে কোনও থ্রেড আটকে থাকে এবং বসে অপেক্ষা করে অপেক্ষা করে এমন একটি থ্রেড আটকে রাখার পরিবর্তে প্রকৃত অ্যাসিনক্রোনাস অপারেশন (সাধারণত I / O) থাকে যা থ্রেডটি থ্রেড পুলে ফিরে যায় এবং অন্য কোনও ক্রিয়াকলাপ সম্পাদন করতে সক্ষম হয়। সর্বোপরি এর অর্থ হ'ল আপনার অ্যাপ্লিকেশনটি কম সংস্থান নিয়ে আরও কিছু করতে পারে এবং যা স্কেলাবিলিটিটি উন্নত করে।


3
@ ফারুক সমস্ত থ্রেড কর্মী থ্রেড। একটি থ্রেডপুল থ্রেড প্রকাশ এবং অন্যটিকে অবরুদ্ধ করা অর্থহীন।
i3arnon

1
আপনি কি বলতে চাইছেন তা আমি নিশ্চিত নই .. তবে যতক্ষণ না আপনি সম্মত হন ততক্ষণ ওয়েবএপিআই-তে সিঙ্কের উপরে অ্যাসিঙ্ক ব্যবহার করার কোনও কারণ নেই তবে তা ঠিক আছে।
i3arnon

@ পেফারুক "সিঙ্ক ওভার সিঙ্ক" (অর্থাত্ await Task.Run(() => CPUIntensive())) এসপিএনটিতে অকেজো। আপনি এটি করে কিছু লাভ করবেন না। আপনি কেবল একটি থ্রেডপুলের থ্রেড প্রকাশ করছেন অন্যটি দখলের জন্য। এটি কেবল সিঙ্ক্রোনাস পদ্ধতিতে কল করার চেয়ে কম দক্ষ।
i3arnon

1
@ পেফারুক না, এটি যুক্তিসঙ্গত নয়। আপনার উদাহরণটি যথাযথভাবে স্বতন্ত্র কাজগুলি পরিচালনা করে। সুপারিশ করার আগে আপনাকে সত্যই এএসকে পড়তে হবে / অপেক্ষা করতে হবে। await Task.WhenAllসমান্তরালভাবে নির্বাহের জন্য আপনাকে ব্যবহার করতে হবে ।
সেরেন বোইসেন

1
@ পেফারুক বোয়েসেন যেমন ব্যাখ্যা করেছেন, আপনার উদাহরণটি কেবল এই সিঙ্ক্রোনাস পদ্ধতিগুলিকে যথাক্রমে কল করার উপরে কোনও মূল্য যুক্ত করে না। আপনি Task.Runএকাধিক থ্রেডে আপনার বোঝার সমান্তরাল করতে চাইলে আপনি ব্যবহার করতে পারেন , তবে এটি "সিঙ্ক ওভার সিঙ্ক" এর অর্থ তা নয়। "অ্যাসিঙ্ক ওভার সিঙ্ক" উল্লেখ করে একটি সিঙ্ক্রোনাসের উপর মোড়ক হিসাবে একটি অ্যাসিঙ্ক পদ্ধতি তৈরি করে। আপনি আমার উত্তরে উদ্ধৃতি দেখতে পারেন।
i3arnon

1

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

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

// GET api/<controller>
[HttpGet]
[Route("pharmacies/{pharmacyId}/page/{page}/{filter?}")]
public async Task<CartTotalsDTO> GetProductsWithHistory(Guid pharmacyId, int page, string filter = null ,[FromUri] bool refresh = false)
{
        var jobID = Guid.NewGuid().ToString()
        var job = new Job
        {
            Id = jobId,
            jobType = "GetProductsWithHistory",
            pharmacyId = pharmacyId,
            page = page,
            filter = filter,
            Created = DateTime.UtcNow,
            Started = null,
            Finished = null,
            User =  {{extract user id in the normal way}}
        };
        jobService.CreateJob(job);

        var timeout = 10*60*1000; //10 minutes
        Stopwatch sw = new Stopwatch();
        sw.Start();
        bool responseReceived = false;
        do
        {
            //wait for the windows service to process the job and build the results in the results table
            if (jobService.GetJob(jobId).Finished == null)
            {
                if (sw.ElapsedMilliseconds > timeout ) throw new TimeoutException();
                await Task.Delay(2000);
            }
            else
            {
                responseReceived = true;
            }
        } while (responseReceived == false);

    //this fetches the results from the temporary results table
    return jobService.GetProductsWithHistory(jobId);
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.