আমি অবাক হয়ে জানতে পেরেছি যে 5 বছর পরে, সমস্ত উত্তর এখনও নীচের এক বা একাধিক সমস্যায় ভুগছে:
- রিডলাইন ব্যতীত একটি ফাংশন ব্যবহৃত হয়, যার ফলে কার্যকারিতা হ্রাস পায়। (পূর্ববর্তী ইনপুটটির জন্য / ব্যাকস্পেস / আপ-কী মুছুন)।
- একাধিকবার আহ্বান করা হলে ফাংশনটি খারাপভাবে আচরণ করে (একাধিক থ্রেড তৈরি করে, অনেকগুলি হ'ল রিডলাইন ঝুলিয়ে থাকে বা অন্যথায় অপ্রত্যাশিত আচরণ করে)।
- ফাংশন একটি ব্যস্ততার জন্য অপেক্ষা করে। অপেক্ষাটি বেশ সেকেন্ড থেকে সময়সীমা পর্যন্ত যে কোনও জায়গায় চলবে বলে আশা করা হওয়ায় এটি একটি ভয়ঙ্কর বর্জ্য, যা একাধিক মিনিট হতে পারে। একটি ব্যস্ততা-অপেক্ষা যা এই সময়ের জন্য প্রচুর পরিমাণে সঞ্চালিত হয় হ'ল সংস্থানগুলির এক ভয়াবহ স্তন্যপান, যা মাল্টিথ্রেডিং দৃশ্যে বিশেষত খারাপ। ব্যস্ততা-অপেক্ষা যদি ঘুমের সাথে সংশোধন করা হয় তবে এটি প্রতিক্রিয়াশীলতার উপর নেতিবাচক প্রভাব ফেলবে, যদিও আমি স্বীকার করি যে এটি সম্ভবত কোনও বিশাল সমস্যা নয়।
আমি বিশ্বাস করি যে আমার সমাধান উপরের সমস্যার কোনওটি না ভেবে মূল সমস্যাটি সমাধান করবে:
class Reader {
private static Thread inputThread;
private static AutoResetEvent getInput, gotInput;
private static string input;
static Reader() {
getInput = new AutoResetEvent(false);
gotInput = new AutoResetEvent(false);
inputThread = new Thread(reader);
inputThread.IsBackground = true;
inputThread.Start();
}
private static void reader() {
while (true) {
getInput.WaitOne();
input = Console.ReadLine();
gotInput.Set();
}
}
// omit the parameter to read a line without a timeout
public static string ReadLine(int timeOutMillisecs = Timeout.Infinite) {
getInput.Set();
bool success = gotInput.WaitOne(timeOutMillisecs);
if (success)
return input;
else
throw new TimeoutException("User did not provide input within the timelimit.");
}
}
কল করা অবশ্যই খুব সহজ:
try {
Console.WriteLine("Please enter your name within the next 5 seconds.");
string name = Reader.ReadLine(5000);
Console.WriteLine("Hello, {0}!", name);
} catch (TimeoutException) {
Console.WriteLine("Sorry, you waited too long.");
}
বিকল্প হিসাবে, আপনি TryXX(out)কনভেনশনটি ব্যবহার করতে পারেন , যেমন শমুয়েলই পরামর্শ দিয়েছেন:
public static bool TryReadLine(out string line, int timeOutMillisecs = Timeout.Infinite) {
getInput.Set();
bool success = gotInput.WaitOne(timeOutMillisecs);
if (success)
line = input;
else
line = null;
return success;
}
যা নিম্নলিখিত হিসাবে বলা হয়:
Console.WriteLine("Please enter your name within the next 5 seconds.");
string name;
bool success = Reader.TryReadLine(out name, 5000);
if (!success)
Console.WriteLine("Sorry, you waited too long.");
else
Console.WriteLine("Hello, {0}!", name);
উভয় ক্ষেত্রেই আপনি Readerসাধারণ Console.ReadLineকলগুলির সাথে কলগুলিতে মিশ্রণ করতে পারবেন না : যদি Readerসময় শেষ হয়ে যায় তবে একটি হ্যাঙ্গিং ReadLineকল আসবে । পরিবর্তে, আপনি যদি একটি সাধারণ (সময়সীমার) ReadLineকল করতে চান তবে কেবল Readerসময়সীমাটি ব্যবহার করুন এবং বাদ দিন, যাতে এটি অসীম সময়সীমার ডিফল্ট হয়।
তাহলে আমি অন্যান্য সমাধানগুলির উল্লিখিত সমস্যাগুলির সম্পর্কে কী করব?
- যেমন আপনি দেখতে পাচ্ছেন, রিডলাইন প্রথম সমস্যাটিকে এড়িয়ে চলে।
- একাধিকবার আহ্বান করা হলে ফাংশনটি সঠিকভাবে আচরণ করে। একটি সময়সীমা ঘটে কিনা তা নির্বিশেষে, কেবলমাত্র একটি মাত্র পটভূমি থ্রেড চলতে থাকবে এবং কেবলমাত্র রিডলাইনে কেবলমাত্র একটি কল সক্রিয় থাকবে। ফাংশনটি কল করার ফলে সর্বদা সর্বশেষতম ইনপুট বা সময়সীমার ফলাফল আসবে এবং ব্যবহারকারীকে তার ইনপুট জমা দেওয়ার জন্য একাধিকবার এন্টার চাপতে হবে না।
- এবং, স্পষ্টতই, ফাংশনটি ব্যস্ততার জন্য অপেক্ষা করে না। পরিবর্তে এটি সম্পদ নষ্ট হওয়া রোধ করতে যথাযথ মাল্টিথ্রেডিং কৌশল ব্যবহার করে।
এই সমাধানটি নিয়ে আমি কেবলমাত্র সমস্যার আগে থেকেই বলেছি এটি থ্রেড-নিরাপদ নয়। তবে একাধিক থ্রেড একই সময়ে ব্যবহারকারীকে ইনপুট চেয়ে নিতে পারে না, সুতরাং যে Reader.ReadLineকোনও উপায়ে কল করার আগে সুসংগত হওয়া উচিত ।