আমি সম্প্রতি স্নিপেটের কোড সিক্যুয়েন্সটি ব্যবহার করেছি যা আমি সম্প্রতি অ্যাসিঙ্ক সলভ ব্যবহার করে পার্থক্য এবং বিভিন্ন সমস্যার চিত্রিত করতে ব্যবহার করেছি।
মনে করুন আপনার জিইউআই ভিত্তিক অ্যাপ্লিকেশনটিতে এমন কিছু ইভেন্ট হ্যান্ডলার রয়েছে যাতে এতে অনেক সময় লাগে এবং তাই আপনি এটিকে অবিচ্ছিন্ন করতে চাই। আপনি যে সিঙ্ক্রোনাস যুক্তি দিয়ে শুরু করেছেন তা এখানে:
while (true) {
string result = LoadNextItem().Result;
if (result.Contains("target")) {
Counter.Value = result.Length;
break;
}
}
লোড নেক্সট আইটেমটি একটি টাস্ক প্রদান করে, যা পরিশেষে আপনি পরিদর্শন করতে চান এমন কিছু ফলাফল আনবে। যদি বর্তমান ফলাফলটি আপনি সন্ধান করেন তবে আপনি ইউআইতে কিছু কাউন্টারটির মান আপডেট করুন এবং পদ্ধতিটি থেকে ফিরে আসুন। অন্যথায়, আপনি লোডনেক্সট আইটেম থেকে আরও আইটেমগুলি প্রক্রিয়াকরণ চালিয়ে যান।
অ্যাসিনক্রোনাস সংস্করণের প্রথম ধারণা: কেবল ধারাবাহিকতা ব্যবহার করুন! এবং আসুন আপাতত লুপিং অংশটি উপেক্ষা করুন। মানে, কী ভুল হতে পারে?
return LoadNextItem().ContinueWith(t => {
string result = t.Result;
if (result.Contains("target")) {
Counter.Value = result.Length;
}
});
দুর্দান্ত, এখন আমাদের এমন একটি পদ্ধতি রয়েছে যা অবরুদ্ধ হয় না! এটি পরিবর্তে ক্রাশ হয়। ইউআই নিয়ন্ত্রণগুলিতে কোনও আপডেট ইউআই থ্রেডে হওয়া উচিত, সুতরাং আপনার এটির জন্য অ্যাকাউন্ট করতে হবে। ধন্যবাদ, কীভাবে ধারাবাহিকতা নির্ধারণ করা উচিত তা নির্দিষ্ট করার একটি বিকল্প রয়েছে এবং কেবলমাত্র এটির জন্য একটি ডিফল্ট রয়েছে:
return LoadNextItem().ContinueWith(t => {
string result = t.Result;
if (result.Contains("target")) {
Counter.Value = result.Length;
}
},
TaskScheduler.FromCurrentSynchronizationContext());
দুর্দান্ত, এখন আমাদের এমন একটি পদ্ধতি রয়েছে যাতে ক্রাশ হয় না! পরিবর্তে এটি নিঃশব্দে ব্যর্থ হয়। ধারাবাহিকতা হ'ল পৃথক কাজগুলি যার সাথে তাদের স্ট্যাটাস পূর্বের কাজটির সাথে আবদ্ধ হয় না। এমনকি লোডনেক্সট আইটেম ত্রুটি থাকলেও, কলকারী কেবলমাত্র একটি কাজ সফলভাবে সম্পন্ন দেখতে পাবে। ঠিক আছে, তারপরে কেবল ব্যতিক্রমটি পাস করুন, যদি একটি থাকে:
return LoadNextItem().ContinueWith(t => {
if (t.Exception != null) {
throw t.Exception.InnerException;
}
string result = t.Result;
if (result.Contains("target")) {
Counter.Value = result.Length;
}
},
TaskScheduler.FromCurrentSynchronizationContext());
দুর্দান্ত, এখন এটি আসলে কাজ করে। একটি আইটেম জন্য। এখন, কিভাবে এই লুপিং সম্পর্কে। দেখা যাচ্ছে, মূল সিঙ্ক্রোনাস ভার্সনের যুক্তির সমতুল্য একটি সমাধান এর মতো দেখতে পাবেন:
Task AsyncLoop() {
return AsyncLoopTask().ContinueWith(t =>
Counter.Value = t.Result,
TaskScheduler.FromCurrentSynchronizationContext());
}
Task<int> AsyncLoopTask() {
var tcs = new TaskCompletionSource<int>();
DoIteration(tcs);
return tcs.Task;
}
void DoIteration(TaskCompletionSource<int> tcs) {
LoadNextItem().ContinueWith(t => {
if (t.Exception != null) {
tcs.TrySetException(t.Exception.InnerException);
} else if (t.Result.Contains("target")) {
tcs.TrySetResult(t.Result.Length);
} else {
DoIteration(tcs);
}});
}
অথবা, উপরের সমস্তটির পরিবর্তে, আপনি একই কাজটি করতে async ব্যবহার করতে পারেন:
async Task AsyncLoop() {
while (true) {
string result = await LoadNextItem();
if (result.Contains("target")) {
Counter.Value = result.Length;
break;
}
}
}
এখন অনেক সুন্দর, তাই না?
Wait
দ্বিতীয় উদাহরণে কল তারপর দুটি স্নিপেট (বেশিরভাগই) সমতুল্য হবে।