दिलचस्प पोस्ट
किसी प्रपत्र के सभी क्षेत्रों को साफ़ करने के लिए jQuery / Javascript फ़ंक्शन सी # पिक्चरबॉक्स पारदर्शी पृष्ठभूमि काम करने के लिए नहीं लगता है स्विफ्ट के साथ स्ट्रिंग में एक सबस्ट्रिंग का सूचकांक एक बहुत ही सरल मल्टीथ्रेडिंग समानांतर यूआरऍल फ़ेचिंग (कतार के बिना) टेक्स्टरिए में कर्सर स्थिति (वर्ण सूचकांक, x / y निर्देशांक नहीं) OSX एल कैपिटन: सुडो पीआईपी ओएसईआरआर स्थापित करें: ऑपरेशन की अनुमति नहीं है वेबवरी में एंड्रॉइड डिस्प्ले / रेस / डिएलेबल क्या आपके .gitconfig में एक फ़ाइल शामिल करना संभव है? इन jQuery के तैयार कार्यों के बीच अंतर क्या है? AngularJS – निर्देश के लिए समारोह पास android.content.ActivityNotFoundException: मैं एक MySQL डाटाबेस में संभव मान कैसे प्राप्त कर सकता हूँ? कैसे सी में एक चार सरणी कॉपी करने के लिए? Generic.xaml के बारे में इतना खास क्या है? एक्सेल: कॉलम / पंक्ति / मैट्रिक्स के बीच डेटा परिवर्तित करने के लिए फ़ार्मुलों

कंसोल में टाइमआउट कैसे जोड़ें। रीडलाइन ()?

मेरे पास कंसोल ऐप है जिसमें मैं उपयोगकर्ता को प्रॉम्प्ट का जवाब देने के लिए x सेकंड देना चाहता हूं। यदि कोई निश्चित अवधि के बाद कोई इनपुट नहीं किया जाता है, तो प्रोग्राम तर्क जारी रखना चाहिए। हम मानते हैं कि एक टाइमआउट खाली प्रतिक्रिया है।

इस आने का सबसे सीधा तरीका क्या है?

वेब के समाधान से एकत्रित समाधान "कंसोल में टाइमआउट कैसे जोड़ें। रीडलाइन ()?"

मुझे यह जानकर हैरान है कि 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); 

दोनों मामलों में, आप सामान्य Console.ReadLine साथ Reader को कॉल नहीं Console.ReadLine हैं। Console.ReadLine कॉल: अगर Reader समय बाहर आता है, तो एक फांसी ReadLine कॉल हो जाएगी। इसके बजाय, यदि आप एक सामान्य (गैर-टाइम) ReadLine कॉल करना चाहते हैं, तो Reader उपयोग करें और समय समाप्त न करें, ताकि यह एक अनंत समय समाप्त होने के लिए डिफॉल्ट हो।

तो अन्य समाधानों की उन समस्याओं के बारे में मैंने क्या बताया?

  • जैसा कि आप देख सकते हैं, पहली समस्या से बचने के लिए, ReadLine का उपयोग किया जाता है
  • कई बार लागू होने पर फ़ंक्शन ठीक से बर्ताव करता है इसके बावजूद कोई समय समाप्ति होती है या नहीं, केवल एक पृष्ठभूमि धागा कभी भी चल रहा होगा और केवल पढ़ने के लिए कॉल करने के लिए केवल कभी भी सक्रिय होगा। फ़ंक्शन कॉल करने से हमेशा नवीनतम इनपुट या टाइमआउट में परिणाम होगा, और उपयोगकर्ता को अपना इनपुट सबमिट करने के लिए एक से अधिक बार दर्ज नहीं करना होगा
  • और जाहिर है, यह फ़ंक्शन किसी व्यस्त-प्रतीक्षा पर भरोसा नहीं करता है इसके बजाय यह संसाधनों को बर्बाद करने से रोकने के लिए उचित मल्टीथ्रेडिंग तकनीकों का उपयोग करता है।

केवल इस समस्या से मुझे लगता है कि यह समाधान नहीं है, यह धागा-सुरक्षित नहीं है हालांकि, कई थ्रेड उपयोगकर्ता को एक ही समय में इनपुट के लिए नहीं पूछ सकते हैं, इसलिए Reader.ReadLine को कॉल करने से पहले सिंक्रनाइज़ेशन हो जाना चाहिए।

 string ReadLine(int timeoutms) { ReadLineDelegate d = Console.ReadLine; IAsyncResult result = d.BeginInvoke(null, null); result.AsyncWaitHandle.WaitOne(timeoutms);//timeout eg 15000 for 15 secs if (result.IsCompleted) { string resultstr = d.EndInvoke(result); Console.WriteLine("Read: " + resultstr); return resultstr; } else { Console.WriteLine("Timed out!"); throw new TimedoutException("Timed Out!"); } } delegate string ReadLineDelegate(); 

कंसोल का उपयोग करने वाला यह तरीका होगा.कई उपलब्ध सहायता?

 class Sample { public static void Main() { ConsoleKeyInfo cki = new ConsoleKeyInfo(); do { Console.WriteLine("\nPress a key to display; press the 'x' key to quit."); // Your code could perform some useful task in the following loop. However, // for the sake of this example we'll merely pause for a quarter second. while (Console.KeyAvailable == false) Thread.Sleep(250); // Loop until input is entered. cki = Console.ReadKey(true); Console.WriteLine("You pressed the '{0}' key.", cki.Key); } while(cki.Key != ConsoleKey.X); } } 

एक तरह से या किसी अन्य को आपको दूसरी धागा की आवश्यकता है आप अपनी खुद की घोषणा करने से बचने के लिए एसिंक्रोनस आईओ का उपयोग कर सकते हैं:

  • मैनुअल रीसेट एवेन्ट घोषित करें, इसे "एव्टी"
  • इनपुट स्ट्रीम प्राप्त करने के लिए सिस्टम पर कॉल करें। Console.OpenStandardInput एक कॉलबैक विधि निर्दिष्ट करें जो इसके डेटा को संग्रहीत करेगी और इब्ट सेट कर देगी।
  • एसिंक्रोनस रीड ऑपरेशन शुरू करने के लिए उस स्ट्रीम के BeginRead विधि को कॉल करें
  • फिर ManualResetEvent पर एक समयबद्ध प्रतीक्षा दर्ज करें
  • अगर प्रतीक्षा समय समाप्त हो जाए, तो पढ़ना रद्द करें

अगर पढ़ा जाता है, तो डेटा सेट करें और आपका मुख्य थ्रेड जारी रहेगा, अन्यथा आप समय समाप्ति के बाद जारी रखेंगे।

 // Wait for 'Enter' to be pressed or 5 seconds to elapse using (Stream s = Console.OpenStandardInput()) { ManualResetEvent stop_waiting = new ManualResetEvent(false); s.BeginRead(new Byte[1], 0, 1, ar => stop_waiting.Set(), null); // ...do anything else, or simply... stop_waiting.WaitOne(5000); // If desired, other threads could also set 'stop_waiting' // Disposing the stream cancels the async read operation. It can be // re-opened if needed. } 

मुझे लगता है कि आपको कंसोल पर एक कुंजी के लिए एक द्वितीयक धागा और मतदान करना होगा। मुझे यह पता है कि यह पूरा करने के लिए कोई निर्माण नहीं किया गया है

यह मेरे लिए काम किया

 ConsoleKeyInfo k = new ConsoleKeyInfo(); Console.WriteLine("Press any key in the next 5 seconds."); for (int cnt = 5; cnt > 0; cnt--) { if (Console.KeyAvailable == true) { k = Console.ReadKey(); break; } else { Console.WriteLine(cnt.ToString()); System.Threading.Thread.Sleep(1000); } } Console.WriteLine("The key pressed was " + k.Key); 

मैं इस समस्या से 5 महीने के लिए संघर्ष करने से पहले एक समाधान पाया जो एक उद्यम सेटिंग में पूरी तरह से काम करता है।

अधिकांश समाधानों के साथ समस्या अब तक यह है कि वे कंसोल के अलावा किसी अन्य चीज़ पर भरोसा करते हैं। रीडलाइन (), और कंसोल। रीडलाइन () के बहुत फायदे हैं:

  • हटाने, बैकस्पेस, तीर कुंजियों आदि के लिए समर्थन।
  • "अप" कुंजी को दबाए जाने और आखिरी आज्ञा को दोहराने की क्षमता (यह बहुत उपयोगी है अगर आप एक पृष्ठभूमि डीबगिंग कंसोल लागू करते हैं जो बहुत अधिक उपयोग हो जाता है)।

मेरा समाधान इस प्रकार है:

  1. Console.ReadLine () का उपयोग करके उपयोगकर्ता इनपुट को संभालने के लिए एक अलग धागा बनाएं।
  2. समय समाप्ति अवधि के बाद, http://inputsimulator.codeplex.com/ का उपयोग करते हुए वर्तमान कंसोल विंडो में एक [प्रविष्ट] कुंजी भेजकर कंसोल.राइडलाइन () को अनवरोधित करें।

नमूना कोड:

  InputSimulator.SimulateKeyPress(VirtualKeyCode.RETURN); 

कंसोल का उपयोग करने वाले धागा को रद्द करने के लिए सही तकनीक सहित इस तकनीक पर अधिक जानकारी। रीडलाइन:

.NET कॉल वर्तमान प्रक्रिया में [प्रवेश] कीस्ट्रोक को भेजने के लिए, जो कंसोल ऐप है?

.NET में एक और थ्रेड को कैसे रद्द करें, जब कहा कि थ्रेड कंसोल निष्पादित कर रहा है। रीडलाइन?

कॉलिंग कंसोल.रिडेल में रीडलाइन () खराब है क्योंकि अगर उपयोगकर्ता 'एंट' को नहीं मारता है तो वह कॉल कभी वापस नहीं आएगा। प्रतिनिधि को निष्पादित थ्रेड अवरुद्ध कर दिया जाएगा जब तक कि उपयोगकर्ता को 'प्रविष्ट' नहीं किया जा सकता, इसे रद्द करने का कोई रास्ता नहीं।

इन कॉलों का अनुक्रम जारी करने से आप अपेक्षित नहीं होंगे। निम्नलिखित पर विचार करें (ऊपर से उदाहरण कंसोल वर्ग का उपयोग करके):

 System.Console.WriteLine("Enter your first name [John]:"); string firstName = Console.ReadLine(5, "John"); System.Console.WriteLine("Enter your last name [Doe]:"); string lastName = Console.ReadLine(5, "Doe"); 

उपयोगकर्ता पहले संकेत के लिए समय समाप्ति की अवधि समाप्त कर देता है, फिर दूसरे संकेत के लिए एक मान दर्ज करता है। दोनों पहले नाम और अंतिम नाम डिफ़ॉल्ट मान शामिल होंगे I जब उपयोगकर्ता 'प्रविष्ट' को हिट करता है, तो पहले रीडलाइन कॉल पूरा हो जाएगा, लेकिन कोड ने उस कॉल को छोड़ दिया है और परिणाम को अनिवार्य रूप से त्याग दिया है। दूसरा रीडलाइन कॉल ब्लॉक करना जारी रखेगा, समय-सीमा समाप्त हो जाएगी और लौटाया गया मूल्य फिर से डिफ़ॉल्ट होगा।

बीटीडब्ल्यू- उपर्युक्त कोड में एक बग है। प्रतीक्षा करें Handle को कॉल करके। बंद करें () आप कार्यकर्ता थ्रेड के नीचे से ईवेंट को बंद कर देते हैं। यदि उपयोगकर्ता समय-सीमा समाप्त होने के बाद 'दर्ज' करता है, तो कार्यकर्ता धागा उस ईवेंट को संकेत देने का प्रयास करेगा जो एक ObjectDisposedException फेंकता है। कार्यकर्ता धागा से अपवाद डाला जाता है, और यदि आपने एक अप्रतिबंधित अपवाद हैंडलर सेटअप नहीं किया है, तो आपकी प्रक्रिया समाप्त हो जाएगी।

मैं प्रश्न में बहुत अधिक पढ़ रहा हो सकता है, लेकिन मैं मानता हूँ कि प्रतीक्षा बूट मेनू के समान होगी, जहां यह 15 सेकंड तक प्रतीक्षा करता है जब तक कि आप कोई कुंजी दबाते नहीं हैं आप या तो (1) ब्लॉकिंग फ़ंक्शन का उपयोग कर सकते हैं या (2) आप थ्रेड, एक ईवेंट और टाइमर का उपयोग कर सकते हैं यह ईवेंट 'जारी' के रूप में कार्य करेगा और तब तक अवरुद्ध होगा जब तक कि टाइमर की समय सीमा समाप्त नहीं हो या एक कुंजी दबाई जाए।

(1) के लिए छद्म कोड होगा:

 // Get configurable wait time TimeSpan waitTime = TimeSpan.FromSeconds(15.0); int configWaitTimeSec; if (int.TryParse(ConfigManager.AppSetting["DefaultWaitTime"], out configWaitTimeSec)) waitTime = TimeSpan.FromSeconds(configWaitTimeSec); bool keyPressed = false; DateTime expireTime = DateTime.Now + waitTime; // Timer and key processor ConsoleKeyInfo cki; // EDIT: adding a missing ! below while (!keyPressed && (DateTime.Now < expireTime)) { if (Console.KeyAvailable) { cki = Console.ReadKey(true); // TODO: Process key keyPressed = true; } Thread.Sleep(10); } 

यदि आप Main() विधि में हैं, तो आप await उपयोग नहीं कर सकते, इसलिए आपको Task.WaitAny() का उपयोग करना होगा। Task.WaitAny() :

 var task = Task.Factory.StartNew(Console.ReadLine); var result = Task.WaitAny(new Task[] { task }, TimeSpan.FromSeconds(5)) == 0 ? task.Result : string.Empty; 

हालांकि, सी # 7.1 एक async Main() विधि बनाने की संभावना का परिचय देता है, इसलिए कार्य का उपयोग करना बेहतर होता है। जब किसी भी Task.WhenAny() संस्करण में आपके पास यह विकल्प होता है:

 var task = Task.Factory.StartNew(Console.ReadLine); var completedTask = await Task.WhenAny(task, Task.Delay(TimeSpan.FromSeconds(5))); var result = object.ReferenceEquals(task, completedTask) ? task.Result : string.Empty; 

मैं दुर्भाग्य से गुलजार की टिप्पणी पर टिप्पणी नहीं कर सकता, लेकिन यहां एक पूर्ण उदाहरण है:

  while (Console.KeyAvailable == false) { Thread.Sleep(250); i++; if (i > 3) throw new Exception("Timedout waiting for input."); } input = Console.ReadLine(); 

संपादित करें : वास्तविक कार्य को एक अलग प्रक्रिया में किया जा रहा है और उस प्रक्रिया को नष्ट कर समस्या को तय किया है, यदि यह समय बाहर आता है। विवरण के लिए नीचे देखें वाह!

बस एक रन दे दिया और यह अच्छी तरह से काम करने के लिए लग रहा था मेरे सहकर्मी के पास एक संस्करण था जो थ्रेड ऑब्जेक्ट का इस्तेमाल करता था, लेकिन मैं प्रतिनिधि प्रकारों की BeginInvoke () विधि को थोड़ा और अधिक सुरुचिपूर्ण बना देता हूं।

 namespace TimedReadLine { public static class Console { private delegate string ReadLineInvoker(); public static string ReadLine(int timeout) { return ReadLine(timeout, null); } public static string ReadLine(int timeout, string @default) { using (var process = new System.Diagnostics.Process { StartInfo = { FileName = "ReadLine.exe", RedirectStandardOutput = true, UseShellExecute = false } }) { process.Start(); var rli = new ReadLineInvoker(process.StandardOutput.ReadLine); var iar = rli.BeginInvoke(null, null); if (!iar.AsyncWaitHandle.WaitOne(new System.TimeSpan(0, 0, timeout))) { process.Kill(); return @default; } return rli.EndInvoke(iar); } } } } 

ReadLine.exe प्रोजेक्ट बहुत सरल है जिसमें एक वर्ग है जो ऐसा दिखता है:

 namespace ReadLine { internal static class Program { private static void Main() { System.Console.WriteLine(System.Console.ReadLine()); } } } 

.NET 4 कार्य का उपयोग करके इस अविश्वसनीय रूप से सरल बनाता है।

सबसे पहले, अपने सहायक का निर्माण करें:

  Private Function AskUser() As String Console.Write("Answer my question: ") Return Console.ReadLine() End Function 

दूसरा, कार्य के साथ निष्पादित करें और प्रतीक्षा करें:

  Dim askTask As Task(Of String) = New TaskFactory().StartNew(Function() AskUser()) askTask.Wait(TimeSpan.FromSeconds(30)) If Not askTask.IsCompleted Then Console.WriteLine("User failed to respond.") Else Console.WriteLine(String.Format("You responded, '{0}'.", askTask.Result)) End If 

इस कार्य को पाने के लिए रीडलाइन कार्यशीलता को पुन: बनाएँ या अन्य खतरनाक हैक्स बनाने की कोई कोशिश नहीं कर रहा है। कार्य हमें एक बहुत ही स्वाभाविक तरीके से प्रश्न हल करने दें।

इसका समाधान करने के लिए साधारण थ्रेडिंग उदाहरण

 Thread readKeyThread = new Thread(ReadKeyMethod); static ConsoleKeyInfo cki = null; void Main() { readKeyThread.Start(); bool keyEntered = false; for(int ii = 0; ii < 10; ii++) { Thread.Sleep(1000); if(readKeyThread.ThreadState == ThreadState.Stopped) keyEntered = true; } if(keyEntered) { //do your stuff for a key entered } } void ReadKeyMethod() { cki = Console.ReadKey(); } 

या पूरी लाइन प्राप्त करने के लिए एक स्थिर स्ट्रिंग ऊपर।

मेरे मामले में यह काम ठीक है:

 public static ManualResetEvent evtToWait = new ManualResetEvent(false); private static void ReadDataFromConsole( object state ) { Console.WriteLine("Enter \"x\" to exit or wait for 5 seconds."); while (Console.ReadKey().KeyChar != 'x') { Console.Out.WriteLine(""); Console.Out.WriteLine("Enter again!"); } evtToWait.Set(); } static void Main(string[] args) { Thread status = new Thread(ReadDataFromConsole); status.Start(); evtToWait = new ManualResetEvent(false); evtToWait.WaitOne(5000); // wait for evtToWait.Set() or timeOut status.Abort(); // exit anyway return; } 

यह ग्लेन स्लेडेन के समाधान का एक पूर्ण उदाहरण है। मैं एक और समस्या के लिए एक परीक्षण मामले के निर्माण के दौरान यह करने के लिए happended यह अतुल्यकालिक I / O और मैन्युअल रीसेट ईवेंट का उपयोग करता है।

 public static void Main() { bool readInProgress = false; System.IAsyncResult result = null; var stop_waiting = new System.Threading.ManualResetEvent(false); byte[] buffer = new byte[256]; var s = System.Console.OpenStandardInput(); while (true) { if (!readInProgress) { readInProgress = true; result = s.BeginRead(buffer, 0, buffer.Length , ar => stop_waiting.Set(), null); } bool signaled = true; if (!result.IsCompleted) { stop_waiting.Reset(); signaled = stop_waiting.WaitOne(5000); } else { signaled = true; } if (signaled) { readInProgress = false; int numBytes = s.EndRead(result); string text = System.Text.Encoding.UTF8.GetString(buffer , 0, numBytes); System.Console.Out.Write(string.Format( "Thank you for typing: {0}", text)); } else { System.Console.Out.WriteLine("oy, type something!"); } } 

एक दूसरा धागा प्राप्त करने का एक अन्य सस्ता तरीका यह है कि यह एक प्रतिनिधि में लपेटें।

उदाहरण के ऊपर एरिक के पद के कार्यान्वयन। इस विशेष उदाहरण का उपयोग सूचना को पढ़ने के लिए किया गया था जिसे पाइप द्वारा कन्सोल ऐप के पास दिया गया था:

  using System; using System.Collections.Generic; using System.IO; using System.Threading; namespace PipedInfo { class Program { static void Main(string[] args) { StreamReader buffer = ReadPipedInfo(); Console.WriteLine(buffer.ReadToEnd()); } #region ReadPipedInfo public static StreamReader ReadPipedInfo() { //call with a default value of 5 milliseconds return ReadPipedInfo(5); } public static StreamReader ReadPipedInfo(int waitTimeInMilliseconds) { //allocate the class we're going to callback to ReadPipedInfoCallback callbackClass = new ReadPipedInfoCallback(); //to indicate read complete or timeout AutoResetEvent readCompleteEvent = new AutoResetEvent(false); //open the StdIn so that we can read against it asynchronously Stream stdIn = Console.OpenStandardInput(); //allocate a one-byte buffer, we're going to read off the stream one byte at a time byte[] singleByteBuffer = new byte[1]; //allocate a list of an arbitary size to store the read bytes List<byte> byteStorage = new List<byte>(4096); IAsyncResult asyncRead = null; int readLength = 0; //the bytes we have successfully read do { //perform the read and wait until it finishes, unless it's already finished asyncRead = stdIn.BeginRead(singleByteBuffer, 0, singleByteBuffer.Length, new AsyncCallback(callbackClass.ReadCallback), readCompleteEvent); if (!asyncRead.CompletedSynchronously) readCompleteEvent.WaitOne(waitTimeInMilliseconds); //end the async call, one way or another //if our read succeeded we store the byte we read if (asyncRead.IsCompleted) { readLength = stdIn.EndRead(asyncRead); if (readLength > 0) byteStorage.Add(singleByteBuffer[0]); } } while (asyncRead.IsCompleted && readLength > 0); //we keep reading until we fail or read nothing //return results, if we read zero bytes the buffer will return empty return new StreamReader(new MemoryStream(byteStorage.ToArray(), 0, byteStorage.Count)); } private class ReadPipedInfoCallback { public void ReadCallback(IAsyncResult asyncResult) { //pull the user-defined variable and strobe the event, the read finished successfully AutoResetEvent readCompleteEvent = asyncResult.AsyncState as AutoResetEvent; readCompleteEvent.Set(); } } #endregion ReadPipedInfo } } 
 string readline = "?"; ThreadPool.QueueUserWorkItem( delegate { readline = Console.ReadLine(); } ); do { Thread.Sleep(100); } while (readline == "?"); 

ध्यान दें कि यदि आप "कंसोल। रीडके" मार्ग पर जाते हैं, तो आप रीडलाइन की कुछ खास सुविधाएं खो देते हैं, अर्थात्:

  • हटाने, बैकस्पेस, तीर कुंजियों आदि के लिए समर्थन।
  • "अप" कुंजी को दबाए जाने और आखिरी आज्ञा को दोहराने की क्षमता (यह बहुत उपयोगी है अगर आप एक पृष्ठभूमि डीबगिंग कंसोल लागू करते हैं जो बहुत अधिक उपयोग हो जाता है)।

समय-सीमा जोड़ने के लिए, सूट के लिए लूप को बदल दें।

यह अच्छा और छोटा नहीं है?

 if (SpinWait.SpinUntil(() => Console.KeyAvailable, millisecondsTimeout)) { ConsoleKeyInfo keyInfo = Console.ReadKey(); // Handle keyInfo value here... } 

मौजूदा उत्तरों की अधिकता के लिए एक और समाधान जोड़ने के लिए कृपया मुझसे नफरत मत करो! यह कंसोल के लिए काम करता है। रीडके (), लेकिन आसानी से रीडलाइन (), आदि के साथ काम करने के लिए संशोधित किया जा सकता है।

जैसा कि "कंसोल। पढ़ें" तरीके अवरुद्ध कर रहे हैं, पढ़ना रद्द करने के लिए स्टड-इन स्ट्रीम को " कुहनी " करने के लिए आवश्यक है।

सिंटैक्स कॉलिंग:

 ConsoleKeyInfo keyInfo; bool keyPressed = AsyncConsole.ReadKey(500, out keyInfo); // where 500 is the timeout 

कोड:

 public class AsyncConsole // not thread safe { private static readonly Lazy<AsyncConsole> Instance = new Lazy<AsyncConsole>(); private bool _keyPressed; private ConsoleKeyInfo _keyInfo; private bool DoReadKey( int millisecondsTimeout, out ConsoleKeyInfo keyInfo) { _keyPressed = false; _keyInfo = new ConsoleKeyInfo(); Thread readKeyThread = new Thread(ReadKeyThread); readKeyThread.IsBackground = false; readKeyThread.Start(); Thread.Sleep(millisecondsTimeout); if (readKeyThread.IsAlive) { try { IntPtr stdin = GetStdHandle(StdHandle.StdIn); CloseHandle(stdin); readKeyThread.Join(); } catch { } } readKeyThread = null; keyInfo = _keyInfo; return _keyPressed; } private void ReadKeyThread() { try { _keyInfo = Console.ReadKey(); _keyPressed = true; } catch (InvalidOperationException) { } } public static bool ReadKey( int millisecondsTimeout, out ConsoleKeyInfo keyInfo) { return Instance.Value.DoReadKey(millisecondsTimeout, out keyInfo); } private enum StdHandle { StdIn = -10, StdOut = -11, StdErr = -12 }; [DllImport("kernel32.dll")] private static extern IntPtr GetStdHandle(StdHandle std); [DllImport("kernel32.dll")] private static extern bool CloseHandle(IntPtr hdl); } 

यहां एक समाधान है जो Console.KeyAvailable का उपयोग करता है। ये कॉल अवरुद्ध कर रहे हैं, लेकिन अगर टीसीएल के जरिए उन्हें अतुल्यकालिक कॉल करने के लिए काफी तुच्छ होना चाहिए, अगर वांछित मैंने मानक रद्द करने के तंत्र का इस्तेमाल किया है ताकि कार्य एसिंक्रोनस पैटर्न और सभी अच्छी चीजों के साथ तार करने में आसान हो।

 public static class ConsoleEx { public static string ReadLine(TimeSpan timeout) { var cts = new CancellationTokenSource(); return ReadLine(timeout, cts.Token); } public static string ReadLine(TimeSpan timeout, CancellationToken cancellation) { string line = ""; DateTime latest = DateTime.UtcNow.Add(timeout); do { cancellation.ThrowIfCancellationRequested(); if (Console.KeyAvailable) { ConsoleKeyInfo cki = Console.ReadKey(); if (cki.Key == ConsoleKey.Enter) { return line; } else { line += cki.KeyChar; } } Thread.Sleep(1); } while (DateTime.UtcNow < latest); return null; } } 

इस के साथ कुछ नुकसान हैं

  • आप मानक नेविगेशन विशेषताएं प्राप्त नहीं करते हैं जो कि ReadLine प्रदान करता है (ऊपर / नीचे तीर स्क्रॉलिंग आदि)।
  • यह इनपुट में '\ 0' वर्णों को इंजेक्ट करता है यदि कोई विशेष कुंजी दबाएं (F1, PrtScn, आदि)। आप कोड को संशोधित करके उन्हें आसानी से फ़िल्टर कर सकते हैं।

यहां समाप्त हो गया क्योंकि एक डुप्लिकेट प्रश्न पूछा गया था। मैं निम्नलिखित समाधान के साथ आया था जो सरलता से दिखता है मुझे यकीन है कि इसमें कुछ कमियां हैं जिन्हें मैंने याद किया।

 static void Main(string[] args) { Console.WriteLine("Hit q to continue or wait 10 seconds."); Task task = Task.Factory.StartNew(() => loop()); Console.WriteLine("Started waiting"); task.Wait(10000); Console.WriteLine("Stopped waiting"); } static void loop() { while (true) { if ('q' == Console.ReadKey().KeyChar) break; } } 

मैं इस उत्तर में आया और समाप्त कर रहा हूं:

  /// <summary> /// Reads Line from console with timeout. /// </summary> /// <exception cref="System.TimeoutException">If user does not enter line in the specified time.</exception> /// <param name="timeout">Time to wait in milliseconds. Negative value will wait forever.</param> /// <returns></returns> public static string ReadLine(int timeout = -1) { ConsoleKeyInfo cki = new ConsoleKeyInfo(); StringBuilder sb = new StringBuilder(); // if user does not want to spesify a timeout if (timeout < 0) return Console.ReadLine(); int counter = 0; while (true) { while (Console.KeyAvailable == false) { counter++; Thread.Sleep(1); if (counter > timeout) throw new System.TimeoutException("Line was not entered in timeout specified"); } cki = Console.ReadKey(false); if (cki.Key == ConsoleKey.Enter) { Console.WriteLine(); return sb.ToString(); } else sb.Append(cki.KeyChar); } } 

Console.KeyAvailable का उपयोग करते हुए एक सरल उदाहरण। Console.KeyAvailable :

 Console.WriteLine("Press any key during the next 2 seconds..."); Thread.Sleep(2000); if (Console.KeyAvailable) { Console.WriteLine("Key pressed"); } else { Console.WriteLine("You were too slow"); } 

अधिक समकालीन और टास्क आधारित कोड ऐसा कुछ दिखाई देगा:

 public string ReadLine(int timeOutMillisecs) { var inputBuilder = new StringBuilder(); var task = Task.Factory.StartNew(() => { while (true) { var consoleKey = Console.ReadKey(true); if (consoleKey.Key == ConsoleKey.Enter) { return inputBuilder.ToString(); } inputBuilder.Append(consoleKey.KeyChar); } }); var success = task.Wait(timeOutMillisecs); if (!success) { throw new TimeoutException("User did not provide input within the timelimit."); } return inputBuilder.ToString(); } 

मेरे पास एक विंडोज़ अनुप्रयोग (विंडोज सर्विस) होने की एक अनोखी स्थिति थी जब प्रोग्राम इंटरैक्टिव रूप से चल रहा है। इंटरएक्टिव (वी.एस. डीबगर या सीएमडी.एक्सए) से, मैं अपना स्टैडीन / स्टडआउट प्राप्त करने के लिए एटैककॉन्स्ल / ऑलोककोनोल का उपयोग किया था। कार्य समाप्त होने तक प्रक्रिया को समाप्त करने के लिए, यूआई थ्रेड को Console.ReadKey(false)Console.ReadKey(false) । मैं इंतजार कर रहा था कि यूआई थ्रेड दूसरे धागे से कर रहा था, इसलिए मैं @JSquaredD द्वारा समाधान के लिए एक संशोधन के साथ आया।

 using System; using System.Diagnostics; internal class PressAnyKey { private static Thread inputThread; private static AutoResetEvent getInput; private static AutoResetEvent gotInput; private static CancellationTokenSource cancellationtoken; static PressAnyKey() { // Static Constructor called when WaitOne is called (technically Cancel too, but who cares) getInput = new AutoResetEvent(false); gotInput = new AutoResetEvent(false); inputThread = new Thread(ReaderThread); inputThread.IsBackground = true; inputThread.Name = "PressAnyKey"; inputThread.Start(); } private static void ReaderThread() { while (true) { // ReaderThread waits until PressAnyKey is called getInput.WaitOne(); // Get here // Inner loop used when a caller uses PressAnyKey while (!Console.KeyAvailable && !cancellationtoken.IsCancellationRequested) { Thread.Sleep(50); } // Release the thread that called PressAnyKey gotInput.Set(); } } /// <summary> /// Signals the thread that called WaitOne should be allowed to continue /// </summary> public static void Cancel() { // Trigger the alternate ending condition to the inner loop in ReaderThread if(cancellationtoken== null) throw new InvalidOperationException("Must call WaitOne before Cancelling"); cancellationtoken.Cancel(); } /// <summary> /// Wait until a key is pressed or <see cref="Cancel"/> is called by another thread /// </summary> public static void WaitOne() { if(cancellationtoken==null || cancellationtoken.IsCancellationRequested) throw new InvalidOperationException("Must cancel a pending wait"); cancellationtoken = new CancellationTokenSource(); // Release the reader thread getInput.Set(); // Calling thread will wait here indefiniately // until a key is pressed, or Cancel is called gotInput.WaitOne(); } } 

यहां एक सुरक्षित समाधान है जो टाइमआउट के बाद थ्रेड को अनवरोधित करने के लिए इनपुट को कंसोल करते हैं। https://github.com/IgoSol/ConsoleReader प्रोजेक्ट एक नमूना उपयोगकर्ता संवाद कार्यान्वयन प्रदान करता है

 var inputLine = ReadLine(5); public static string ReadLine(uint timeoutSeconds, Func<uint, string> countDownMessage, uint samplingFrequencyMilliseconds) { if (timeoutSeconds == 0) return null; var timeoutMilliseconds = timeoutSeconds * 1000; if (samplingFrequencyMilliseconds > timeoutMilliseconds) throw new ArgumentException("Sampling frequency must not be greater then timeout!", "samplingFrequencyMilliseconds"); CancellationTokenSource cts = new CancellationTokenSource(); Task.Factory .StartNew(() => SpinUserDialog(timeoutMilliseconds, countDownMessage, samplingFrequencyMilliseconds, cts.Token), cts.Token) .ContinueWith(t => { var hWnd = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle; PostMessage(hWnd, 0x100, 0x0D, 9); }, TaskContinuationOptions.NotOnCanceled); var inputLine = Console.ReadLine(); cts.Cancel(); return inputLine; } private static void SpinUserDialog(uint countDownMilliseconds, Func<uint, string> countDownMessage, uint samplingFrequencyMilliseconds, CancellationToken token) { while (countDownMilliseconds > 0) { token.ThrowIfCancellationRequested(); Thread.Sleep((int)samplingFrequencyMilliseconds); countDownMilliseconds -= countDownMilliseconds > samplingFrequencyMilliseconds ? samplingFrequencyMilliseconds : countDownMilliseconds; } } [DllImport("User32.Dll", EntryPoint = "PostMessageA")] private static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam); 

This seems to be the simplest, working solution, that doesn't use any native APIs:

  static Task<string> ReadLineAsync(CancellationToken cancellation) { return Task.Run(() => { while (!Console.KeyAvailable) { if (cancellation.IsCancellationRequested) return null; Thread.Sleep(100); } return Console.ReadLine(); }); } 

उदाहरण उपयोग:

  static void Main(string[] args) { AsyncContext.Run(async () => { CancellationTokenSource cancelSource = new CancellationTokenSource(); cancelSource.CancelAfter(1000); Console.WriteLine(await ReadLineAsync(cancelSource.Token) ?? "null"); }); }