আপনি কেন কোনও পদ্ধতির 'প্রতীক্ষা' করবেন, এবং তারপরে তার রিটার্নের মানটি তাত্ক্ষণিকভাবে জিজ্ঞাসাবাদ করবেন?


24

ইন এই দুটিই MSDN নিবন্ধ , নিম্নলিখিত উদাহরণে কোড প্রদান করা হয় (সামান্য সংক্ষিপ্ততা জন্য সম্পাদনা):

public async Task<ActionResult> Details(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }

    Department department = await db.Departments.FindAsync(id);

    if (department == null)
    {
        return HttpNotFound();
    }

    return View(department);
}

FindAsyncপদ্ধতি আহরণ Departmentতার আইডি দিয়ে বস্তু, এবং একটি ফেরৎ Task<Department>। তারপরে বিভাগটি তাত্ক্ষণিকভাবে তা নাল কিনা তা পরীক্ষা করে দেখা হয়। আমি এটি বুঝতে পেরেছি, এইভাবে টাস্কের মান জিজ্ঞাসা করা অপেক্ষিত পদ্ধতির মানটি ফিরে না আসা পর্যন্ত কোড কার্যকরকরণকে ব্লক করে দেবে , কার্যকরভাবে এটিকে একটি সিঙ্ক্রোনাস কল করে।

আপনি কেন কখনও এই কাজ করবেন? আপনি কেবল Find(id)তাত্ক্ষণিকভাবে যেকোনভাবে ব্লক করতে চলেছেন, তবে কেবল সিঙ্ক্রোনাস পদ্ধতিটি কল করা কি সহজ হবে না?


এটি বাস্তবায়ন সম্পর্কিত হতে পারে। ... else return null;তারপরে আপনার যাচাই করা দরকার যে পদ্ধতিটি আপনাকে জিজ্ঞাসা করা বিভাগটি আসলে খুঁজে পেয়েছিল।
জেরেমি Kato

আমি একজন asp.net কোনো দেখতে পাচ্ছ না, কিন্তু একটি destop অ্যাপ্লিকেশানে, এই ভাবে করছেন আপনি UI জমাকৃত নেই দ্বারা
Rémi

এখানে একটি লিঙ্ক দেওয়া হয়েছে যা ডিজাইনারের কাছ থেকে অপেক্ষা করা ধারণাটি ব্যাখ্যা করে ... এমএসডিএন.মাইক্রোসফটকম /en-us/magazine/hh456401.aspx
জন

থ্রেড যোগাযোগের স্যুইচগুলি আপনাকে কমিয়ে দিচ্ছে বা মেমরির ব্যবহারের ফলে অনেকগুলি থ্রেড স্ট্যাক আপনার জন্য ইস্যু হলে অ্যাওএসইটি কেবল এএসপি.এনইটি নিয়েই ভাবা উচিত।
ইয়ান

উত্তর:


24

আমি এটি বুঝতে পেরেছি, এইভাবে টাস্কের মান জিজ্ঞাসা করা অপেক্ষিত পদ্ধতির মানটি ফিরে না আসা পর্যন্ত কোড কার্যকরকরণকে অবরুদ্ধ করে দেবে, কার্যকরভাবে এটিকে একটি সিঙ্ক্রোনাস কল করে।

বেশ না।

আপনি যখন কল করেন await db.Departments.FindAsync(id)তখন কাজটি বন্ধ হয়ে যায় এবং বর্তমান থ্রেডটি অন্য ক্রিয়াকলাপের জন্য পুলটিতে ফিরে আসে। মৃত্যুদন্ড কার্যকর করা অবরুদ্ধ করা হয়েছে (যেমন departmentঠিক পরে ব্যবহার করা নির্বিশেষে হবে , যদি আমি জিনিসগুলি সঠিকভাবে বুঝতে পারি) তবে থ্রেড নিজেই অপ্র-মেশিনের অপারেশনটি সম্পন্ন হওয়ার অপেক্ষায় থাকাকালীন অন্য জিনিসগুলি ব্যবহার করতে মুক্ত is কোনও ইভেন্ট বা সমাপ্তি বন্দর দ্বারা সংকেত)।

যদি আপনি ফোন করেন d.Departments.Find(id)তবে থ্রেডটি সেখানে বসে প্রতিক্রিয়ার জন্য অপেক্ষা করবে, যদিও বেশিরভাগ প্রসেসিং ডিবিতে করা হচ্ছে।

আপনি ডিস্কের সাথে আবদ্ধ হয়ে কার্যকরভাবে সিপিইউ সংস্থানগুলি মুক্ত করে দিচ্ছেন।


2
তবে আমি ভেবেছিলাম যে awaitসমস্তগুলি একই থ্রেডের ধারাবাহিকতা হিসাবে পদ্ধতিটির বাকী অংশগুলিতে সাইন ইন করা হয়েছিল (ব্যতিক্রম রয়েছে; কিছু অ্যাসিঙ্ক পদ্ধতি তাদের নিজস্ব থ্রেড স্পিন করে), বা asyncপদ্ধতিটিতে একই থ্রেডের ধারাবাহিকতা হিসাবে সাইন ইন করে অনুমতি দেয় কার্যকর করার জন্য অবশিষ্ট কোড (আপনি দেখতে পাচ্ছেন, আমি কীভাবে asyncকাজ করে তাতে স্ফটিক-পরিষ্কার নয় )। আপনি যা বর্ণনা করছেন তা একটি পরিশীলিত রূপের মতো শোনাচ্ছেThread.Sleep(untilReturnValueAvailable)
রবার্ট হার্ভে

1
@ রবার্টহারভে - এটি এটি একটি ধারাবাহিকতা হিসাবে নির্ধারণ করে, তবে একবার আপনি কাজটি (এবং এর ধারাবাহিকতা) প্রসেস করার জন্য পাঠিয়ে দিলে, চালানোর কিছুই বাকি নেই। আপনি যদি এটি নির্দিষ্ট না করেন তবে এটি একই থ্রেডে থাকার নিশ্চয়তা নেই ( ConfigureAwaitআইরিচের মাধ্যমে )।
টেলাস্টিন

1
আমার উত্তর দেখুন ... ধারাবাহিকতা ডিফল্টরূপে মূল থ্রেডে ফিরে মার্শাল করা হবে।
মাইকেল ব্রাউন

2
আমি মনে করি আমি এখানে যা মিস করছি তা আমি দেখতে পাচ্ছি। awaitএটির কোনও সুবিধা দেওয়ার জন্য, এএসপি.এনইটি এমভিসি ফ্রেমওয়ার্কটিতে অবশ্যই কল করতে হবে public async Task<ActionResult> Details(int? id)। অন্যথায়, আসল কলটি কেবল অবরুদ্ধ হবে, সমাধানের জন্য অপেক্ষা করছে department == null
রবার্ট হার্ভে

2
@ রবার্টহারভে await ..."রিটার্ন" করার সময় FindAsyncকল শেষ হয়ে গেছে। এটিই অপেক্ষা করে। একে অপেক্ষার বলা হয় কারণ এটি আপনার কোডকে জিনিসগুলির জন্য অপেক্ষা করে। (তবে নোট করুন যে বর্তমান থ্রেডটি জিনিসগুলির জন্য অপেক্ষা করার মতো নয়)
ব্যবহারকারী 253751

17

আমি সত্যিই ঘৃণা করি যে উদাহরণগুলির মধ্যে কোনওটিই কীভাবে টাস্কটির অপেক্ষার আগে কয়েকটি লাইনের জন্য অপেক্ষা করা সম্ভব তা দেখায় না। এই বিবেচনা.

Foo foo = await getFoo();
Bar bar = await getBar();

Console.WriteLine(“Do some other stuff to prepare.”);

doStuff(foo, bar);

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

Task<Foo> foo = getFoo();
Task<Bar> bar = getBar();

Console.WriteLine(“Do some other stuff to prepare.”);

doStuff(await foo, await bar);

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


1
এইচএম, এটি কোর / থ্রেড সম্পর্কে কম এবং অ্যাসিক্রোনাস কলগুলি সঠিকভাবে ব্যবহার করা সম্পর্কে আরও বেশি।
উত্সাহক

আপনি ভুল হন না সে কারণেই আমি আমার উত্তরে "ব্লক" উদ্ধৃত করেছি। থ্রেডের উল্লেখ না করেই এই স্টাফটির সাথে কথা বলা শক্ত, তবে এখনও স্বীকৃতি দেওয়ার সময় মাল্টি-থ্রেডিং জড়িত থাকতে পারে বা নাও থাকতে পারে।
রাবারডাক

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

"এর মধ্যে খুব একটা বুদ্ধি নেই।" - এর মধ্যে প্রচুর জ্ঞান আছে। যেসব ক্ষেত্রে "অন্যান্য জিনিসগুলি করা চালিয়ে যান" খুব একই পদ্ধতিতে প্রযোজ্য তা সাধারণ নয়; এটি আরও সাধারণ যে আপনি কেবল চান awaitএবং পরিবর্তে থ্রেডটি সম্পূর্ণ আলাদা জিনিস করতে দিন।
সেবাস্তিয়ান রেডল

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

6

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

কলিং ফাংশনটি ব্লক করে না। যা ঘটে তা হ'ল ডিপার্টমেন্টের কার্যভার এবং অপেক্ষার কীওয়ার্ড অনুসরণ করে সমস্ত কিছু বন্ধ হয়ে যায় এবং সমস্ত উদ্দেশ্য এবং উদ্দেশ্যে টাস্ক.কন্টিন্যউইথ পদ্ধতিতে (ফাইন্ডএন্সিঙ্ক ফাংশনটি স্বয়ংক্রিয়ভাবে একটি ভিন্ন থ্রেডে কার্যকর করা হয়) হয়ে যায়।

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

সুতরাং যা হয় তা হ'ল আপনি অ্যাসিঙ্ক অপারেশনের ম্যাজিকটি পেয়ে যান, কোনও সমস্যা ছাড়াই।


1

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


না এখানে কোনও অবরুদ্ধতা নেই। এটি অ্যাসিঙ্ক পদ্ধতিটি ইতিমধ্যে শেষ না হওয়া অবধি বিভাগে কখনই == নালার হবে না।
স্টিভ

1
async awaitসাধারণত নতুন থ্রেড তৈরি করে না, এবং তা হয়ে গেলেও, আপনাকে এখনও বিভাগের মানটি বাতিল করার জন্য অপেক্ষা করতে হবে।
রবার্ট হার্ভে

2
সুতরাং মূলত আপনি যা বলছেন তা হ'ল এটির কোনও উপকারে আসার জন্য, কলটিও public async Task<ActionResult> অবশ্যই সম্পাদনাawait
রবার্ট হার্ভে

2
@ রবার্টহারভে হ্যাঁ, আপনি ধারণা পেয়েছেন। অ্যাসিঙ্ক / অ্যাওয়েট মূলত ভাইরাল। আপনি যদি একটি ফাংশনটির "অপেক্ষা" করেন, আপনাকে কল করে এমন কোনও ফাংশনের জন্যও অপেক্ষা করা উচিত। বা awaitমিশ্রিত করা উচিত নয় , কারণ এটি অচলাবস্থা তৈরি করতে পারে। অ্যাসিঙ্ক / অপেক্ষার শৃঙ্খলা সাধারণত একটি স্বাক্ষরযুক্ত একটি ফাংশনে শেষ হয় যা বেশিরভাগ ইভেন্ট হ্যান্ডলারের জন্য বা সরাসরি ইউআই উপাদানগুলির দ্বারা ডাকা ফাংশনগুলির জন্য ব্যবহৃত হয়। .Wait().Resultasync void
কেচালোক্স

1
@ স্টিভ - " ... সুতরাং এটি নিজস্ব থ্রেডে থাকবে " "না, পড়ুন টাস্কগুলি এখনও থ্রেড নয় এবং অ্যাসিঙ্ক সমান্তরাল নয় । এর মধ্যে প্রকৃত আউটপুট অন্তর্ভুক্ত রয়েছে যা দেখায় যে একটি নতুন থ্রেড তৈরি হয়নি।
টুলমেকারস্টেভ

1

আমি চুক্তির মতো "অ্যাসিঙ্ক" সম্পর্কে ভাবতে চাই, এমন একটি চুক্তি বলে যে "আপনার যদি প্রয়োজন হয় তবে আমি এই অ্যাসিনক্রোনালি সম্পাদন করতে পারি, তবে আপনি আমাকে অন্য কোনও সিনক্রোনাস ফাংশনের মতো কল করতে পারেন"।

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

Task<Department> deptTask = db.Departments.FindAsync(id);

এবং তারপরে, বলুন, আপনি যে ফাংশনটি কল করেছেন তা 10 টি লাইন নীচে

Department d = await deptTask;

অতএব এটি একটি অ্যাসিক্রোনাস ফাংশন হিসাবে বিবেচনা করা।

এটা আপনার উপর নির্ভর করছে.


1
এটি আরও অনেকটা "আমি বার্তাটি অবিচ্ছিন্নভাবে পরিচালনা করার অধিকার সংরক্ষণ করি, ফলাফল পাওয়ার জন্য এটি ব্যবহার করি"।
উত্সাহক

-1

"যদি আপনি যেভাবে অবিলম্বে অবরুদ্ধ করতে চান" আনোসারটি হ্যাঁ "হ্যাঁ"। কেবলমাত্র যখন আপনার দ্রুত প্রতিক্রিয়া দরকার হবে, তখনই অপেক্ষা করুন / অ্যাসিঙ্কটি বুদ্ধিমান হয়ে উঠুন। উদাহরণস্বরূপ, ইউআই থ্রেডটি সত্যই একটি অ্যাসিঙ্ক পদ্ধতিতে আসে, ইউআই থ্রেড ফিরে আসবে এবং বোতাম ক্লিক শুনতে থাকবে, যখন "অপেক্ষার" নীচের কোডটি অন্য থ্রেড দ্বারা উত্তেজিত হবে এবং শেষ পর্যন্ত ফলাফল পাবে।


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