উত্তর:
আপনি যখন async
/ ব্যবহার করেন তখন await
কোনও গ্যারান্টি নেই যে আপনি যখন কল করবেন তখন যে পদ্ধতিটি করা await FooAsync()
হবে তা আসলে অ্যাসিনক্রোনালি চালিত হবে। অভ্যন্তরীণ বাস্তবায়ন সম্পূর্ণ সিঙ্ক্রোনাস পথ ব্যবহার করে ফিরতে মুক্ত।
আপনি যদি এমন কোনও এপিআই তৈরি করেন যেখানে এটি গুরুতর যে আপনি অবরুদ্ধ করবেন না এবং আপনি কিছু কোডকে অবিচ্ছিন্নভাবে চালনা করছেন, এবং এমন একটি সম্ভাবনা রয়েছে যে কল করা পদ্ধতিটি সিঙ্ক্রোনিকভাবে চলবে (কার্যকরভাবে অবরুদ্ধ করা), await Task.Yield()
আপনার পদ্ধতিটি অ্যাসিক্রোনাস হতে বাধ্য করবে এবং ফিরে আসবে এই সময়ে নিয়ন্ত্রণ কোডের বাকী অংশটি পরবর্তী সময়ে কার্যকর করা হবে (যে সময়ে এটি এখনও সুসংগতভাবে চলতে পারে) বর্তমান প্রসঙ্গে।
আপনি যদি একটি অ্যাসিনক্রোনাস পদ্ধতি তৈরি করেন যা কিছু "দীর্ঘ চলমান" সূচনা প্রয়োজন, যেমন:
private async void button_Click(object sender, EventArgs e)
{
await Task.Yield(); // Make us async right away
var data = ExecuteFooOnUIThread(); // This will run on the UI thread at some point later
await UseDataAsync(data);
}
Task.Yield()
কল ছাড়াই , পদ্ধতিটি প্রথম কলটিতে সমস্তভাবে সিঙ্ক্রোনসিভভাবে কার্যকর করবে await
।
Task.Run
এটি প্রয়োগ করতে একটি ব্যবহার ExecuteFooOnUIThread
করেন তবে থাই পুলটিতে চলবে, ইউআই থ্রেড নয়। এর সাথে await Task.Yield()
, আপনি এটিকে এমনভাবে অবিচ্ছিন্ন হতে বাধ্য করেন যে পরবর্তী কোডটি এখনও বর্তমান প্রসঙ্গে (সময়ের পরে ঠিক সময়ে) চালিত হয়। এটি আপনি সাধারণত করেন এমন কিছু নয়, তবে এটি দুর্দান্ত যে কোনও অদ্ভুত কারণে যদি এটির প্রয়োজন হয় তবে বিকল্প রয়েছে।
ExecuteFooOnUIThread()
খুব দীর্ঘ সময় চলতে থাকে তবে এটি এখনও কোনও সময়ে ইউআই থ্রেডকে দীর্ঘ সময়ের জন্য অবরুদ্ধ করে এবং ইউআইকে প্রতিক্রিয়াহীন করে তুলবে, এটি কি সঠিক?
অভ্যন্তরীণভাবে, await Task.Yield()
কেবল পারেন বর্তমান সিঙ্ক্রোনাইজেশন প্রসঙ্গ বা একটি র্যান্ডম পুকুর থ্রেডে ধারাবাহিকতা queues, যদি SynchronizationContext.Current
হয় null
।
এটি কাস্টম ওয়েটার হিসাবে দক্ষতার সাথে প্রয়োগ করা হয়েছে। অভিন্ন প্রভাব উত্পাদন একটি কম দক্ষ কোড এই হিসাবে সহজ হতে পারে:
var tcs = new TaskCompletionSource<bool>();
var sc = SynchronizationContext.Current;
if (sc != null)
sc.Post(_ => tcs.SetResult(true), null);
else
ThreadPool.QueueUserWorkItem(_ => tcs.SetResult(true));
await tcs.Task;
Task.Yield()
কিছু অদ্ভুত এক্সিকিউশন প্রবাহ পরিবর্তনের জন্য একটি শর্ট-কাট হিসাবে ব্যবহার করা যেতে পারে। উদাহরণ স্বরূপ:
async Task DoDialogAsync()
{
var dialog = new Form();
Func<Task> showAsync = async () =>
{
await Task.Yield();
dialog.ShowDialog();
}
var dialogTask = showAsync();
await Task.Yield();
// now we're on the dialog's nested message loop started by dialog.ShowDialog
MessageBox.Show("The dialog is visible, click OK to close");
dialog.Close();
await dialogTask;
// we're back to the main message loop
}
এটি বলেছিল, আমি এমন কোনও ক্ষেত্রে ভাবতে পারি না যেখানে ডাব্লু / যথাযথ টাস্ক শিডিয়ুলারের Task.Yield()
সাথে প্রতিস্থাপন করা যায় না Task.Factory.StartNew
।
আরো দেখুন:
var dialogTask = await showAsync();
?
var dialogTask = await showAsync()
সংকলন করবে না কারণ await showAsync()
এক্সপ্রেশনটি কোনও ফিরে আসে না Task
(এটি ব্যতীত ভিন্ন await
)। এটি বলে, যদি আপনি await showAsync()
এটি করেন তবে ডায়ালগটি বন্ধ হয়ে যাওয়ার পরে তার কার্যকর করা পুনরায় শুরু করা হবে, এটাই আলাদা। কারণ window.ShowDialog
এটি একটি সিঙ্ক্রোনাস এপিআই (এটি বার্তা পাম্প সত্ত্বেও)। সেই কোডটিতে, আমি ডায়ালগটি এখনও প্রদর্শিত থাকার সময় চালিয়ে যেতে চেয়েছিলাম।
এর একটি ব্যবহার Task.Yield()
হ'ল অ্যাসিঙ্ক পুনরাবৃত্তি করার সময় স্ট্যাকের ওভারফ্লো প্রতিরোধ করা। Task.Yield()
সিঙ্ক্রোনাস ধারাবাহিকতা রোধ করে। তবে নোট করুন, এর ফলে এটি আউটআফমিউরি ব্যতিক্রম ঘটতে পারে (যেমন ট্রায়ঙ্কো উল্লেখ করেছেন)। অন্তহীন পুনরাবৃত্তি এখনও নিরাপদ নয় এবং আপনি সম্ভবত লুপ হিসাবে পুনরাবৃত্তি পুনর্লিখন আরও ভাল।
private static void Main()
{
RecursiveMethod().Wait();
}
private static async Task RecursiveMethod()
{
await Task.Delay(1);
//await Task.Yield(); // Uncomment this line to prevent stackoverlfow.
await RecursiveMethod();
}
await Task.Delay(1)
প্রতিরোধের জন্য যথেষ্ট। (কনসোল অ্যাপ
Task.Yield()
অ্যাসিঙ্ক পদ্ধতির মক বাস্তবায়নে ব্যবহৃত হতে পারে।
await Task.Yield()
পদ্ধতিটিকে অ্যাসিঙ্ক হতে বাধ্য করে, তবে আমরা কেন "আসল" অ্যাসিঙ্ক কোডটি লিখতে বিরক্ত করব? একটি ভারী সিঙ্ক পদ্ধতি কল্পনা করুন। এ্যাসিঙ্ক তৈরি করতে, কেবল যুক্ত করুনasync
এবংawait Task.Yield()
শুরুতে এবং যাদুকরীভাবে, এটি অ্যাসিঙ্ক হবে? এটি বেশিরভাগ ক্ষেত্রে সমস্ত সিঙ্ক কোডটি মোড়ানোTask.Run()
এবং একটি জাল অ্যাসিঙ্ক পদ্ধতি তৈরির মতো হবে ।