গতকাল আমি নতুন সি # "অ্যাসিঙ্ক" বৈশিষ্ট্য সম্পর্কে একটি বক্তব্য দিচ্ছিলাম, বিশেষত উত্পন্ন কোডটি কীভাবে এবং the GetAwaiter()
/ BeginAwait()
/ EndAwait()
কলগুলির মতো দেখাচ্ছে তা আবিষ্কার করে।
আমরা সি # সংকলক দ্বারা উত্পাদিত রাষ্ট্র মেশিনে কিছু বিশদে দেখেছি এবং দুটি দিক ছিল যা আমরা বুঝতে পারি না:
- উত্পন্ন শ্রেণিতে কেন একটি
Dispose()
পদ্ধতি এবং একটি$__disposing
ভেরিয়েবল রয়েছে, যা কখনই ব্যবহৃত হয় না বলে মনে হয় (এবং শ্রেণিটি প্রয়োগ করে নাIDisposable
)। - অভ্যন্তরীণ
state
ভেরিয়েবলটি কোনও কল করার আগে কেন 0 তে সেট করা হয়EndAwait()
, যখন 0 সাধারণত প্রদর্শিত হয় "এটিই প্রাথমিক প্রবেশ পয়েন্ট" mean
আমি সন্দেহ করি যে অ্যাসিঙ্ক পদ্ধতিতে আরও আকর্ষণীয় কিছু করে প্রথম পয়েন্টটির উত্তর দেওয়া যেতে পারে, যদিও কারও কাছে আরও কিছু তথ্য থাকলে আমি তা শুনে খুশি হব। এই প্রশ্নটি তবে দ্বিতীয় পয়েন্টটি সম্পর্কে আরও বেশি।
এখানে নমুনা কোডের একটি খুব সাধারণ টুকরো:
using System.Threading.Tasks;
class Test
{
static async Task<int> Sum(Task<int> t1, Task<int> t2)
{
return await t1 + await t2;
}
}
... এবং এখানে কোডটি সেই MoveNext()
পদ্ধতির জন্য উত্পন্ন হয় যা রাষ্ট্র মেশিন প্রয়োগ করে। এটি সরাসরি প্রতিফলকের কাছ থেকে অনুলিপি করা হয়েছে - আমি অব্যক্ত পরিবর্তনশীল নামগুলি স্থির করিনি:
public void MoveNext()
{
try
{
this.$__doFinallyBodies = true;
switch (this.<>1__state)
{
case 1:
break;
case 2:
goto Label_00DA;
case -1:
return;
default:
this.<a1>t__$await2 = this.t1.GetAwaiter<int>();
this.<>1__state = 1;
this.$__doFinallyBodies = false;
if (this.<a1>t__$await2.BeginAwait(this.MoveNextDelegate))
{
return;
}
this.$__doFinallyBodies = true;
break;
}
this.<>1__state = 0;
this.<1>t__$await1 = this.<a1>t__$await2.EndAwait();
this.<a2>t__$await4 = this.t2.GetAwaiter<int>();
this.<>1__state = 2;
this.$__doFinallyBodies = false;
if (this.<a2>t__$await4.BeginAwait(this.MoveNextDelegate))
{
return;
}
this.$__doFinallyBodies = true;
Label_00DA:
this.<>1__state = 0;
this.<2>t__$await3 = this.<a2>t__$await4.EndAwait();
this.<>1__state = -1;
this.$builder.SetResult(this.<1>t__$await1 + this.<2>t__$await3);
}
catch (Exception exception)
{
this.<>1__state = -1;
this.$builder.SetException(exception);
}
}
এটি দীর্ঘ, তবে এই প্রশ্নের গুরুত্বপূর্ণ লাইনগুলি হ'ল:
// End of awaiting t1
this.<>1__state = 0;
this.<1>t__$await1 = this.<a1>t__$await2.EndAwait();
// End of awaiting t2
this.<>1__state = 0;
this.<2>t__$await3 = this.<a2>t__$await4.EndAwait();
উভয় ক্ষেত্রেই পরের স্পষ্টত পর্যবেক্ষণ হওয়ার আগেই রাষ্ট্রটি আবার পরিবর্তন করা হয় ... তবে কেন একে একে 0 এ সেট করবেন? যদি MoveNext()
এই মুহুর্তে আবার ডাকা হয় (হয় প্রত্যক্ষ বা মাধ্যমে Dispose
) এটি আবার অ্যাসিঙ্ক পদ্ধতিটি কার্যকরভাবে আবার শুরু করবে, যা আমি যতটা বলতে পারি যথাযথভাবে অনুপযুক্ত ... যদি বলা MoveNext()
হয় না এবং রাজ্য পরিবর্তন অপ্রাসঙ্গিক।
এটি কি কেবল এসিঙ্কের জন্য পুনরাবৃত্তকারী ব্লক জেনারেশন কোডটি পুনরায় ব্যবহার করে সংকলকটির একটি পার্শ্ব-প্রতিক্রিয়া, যেখানে এর আরও স্পষ্ট ব্যাখ্যা থাকতে পারে?
গুরুত্বপূর্ণ অস্বীকৃতি
অবশ্যই এটি কেবল একটি সিটিপি সংকলক। আমি চূড়ান্ত প্রকাশের আগে জিনিসগুলি পরিবর্তনের পুরোপুরি প্রত্যাশা করি - এবং সম্ভবত পরবর্তী সিটিপি প্রকাশের আগেও। এই প্রশ্নটি কোনওভাবেই দাবি করার চেষ্টা করছে না এটি সি # সংকলক বা এর মতো অন্য কোনও ত্রুটি। আমি কেবল এটি মিস করার কোনও সূক্ষ্ম কারণ আছে কিনা তা নিয়ে চেষ্টা করার চেষ্টা করছি :)