2008-10-17 19 views
8

Ich muss um Eingabe in der Konsole bitten und warten Sie, bis einige Sekunden eine Minute nach dem ich muss auf einen Wert voreingestellt werden. Wie kann man im Prinzip die Zeit für die Konsoleneingabe in C# eingeben und mit den Standardeinstellungen fortfahren? Wenn Sie Beispielcode haben, wäre das großartig.Wie warte ich auf Konsole Eingabe in C# für 15 Sekunden oder so

+0

sollten Sie nicht wirklich Dinge mit "etc" markieren. Es ist ziemlich bedeutungslos, also habe ich es nur mit C# gepriesen. – Mark

+0

Und "warten" ist wirklich auch nicht sehr gut. Ich habe passendere Tags hinzugefügt. –

+1

möglich Duplikat von [Wie fügt man ein Timeout zu Console.ReadLine() hinzu?] (Http://stackoverflow.com/questions/57615/how-to-add-a-timeout-to-console-readline) –

Antwort

0

Eine Möglichkeit wäre, eine Schleife zu erstellen und Console.In.Peek() aufzurufen, um auf die Eingabe zu warten oder genügend Zeit zu haben.

2

Siehe here, es verwendet eine nette kleine Polling-Technik auf der Konsole, die zwar ein bisschen roh, sehr effektiv.

3

Sie könnten das Timer-Objekt in System.Timers.Timer verwenden und auf 60 Sekunden einstellen, aktivieren Sie es und wenn jemand etwas in die Konsole eingibt, deaktivieren Sie es einfach, wenn nicht, dann behandeln Sie einfach was passiert in der Timer.Elapsed Veranstaltung.

static void Main(string[] args) 
     { 
      System.Timers.Timer timer = new System.Timers.Timer(60000); 
      timer.Elapsed += new System.Timers.ElapsedEventHandler(T_Elapsed); 
      timer.Start(); 
      var i = Console.ReadLine(); 
      if (string.IsNullOrEmpty(i)) 
      { 
       timer.Stop(); 
       Console.WriteLine("{0}", i); 
      } 
     } 

     static void T_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
     { 
      Console.WriteLine("Defult Values Used"); 
      var T = (Timer)sender; 
      T.Stop; 

     } 

Nicht sicher, ob dies der beste Weg ist. Ich habe das getestet, aber wie gesagt, es ist vielleicht nicht der beste Weg.

+3

Das Problem Bei diesem Modell ist ReadLine ein blockierender Aufruf, der erst zurückkehrt, wenn die Zeile eingegeben wurde. Während also der Standardwert gesendet werden kann, wenn der Timer abgelaufen ist, wird das Programm nicht fortgesetzt, bis der Text eingegeben wurde. – ICR

+0

mmm yeah habe nicht wirklich daran gedacht. Bugger –

2

Sie sollten beispielsweise ein Befehlszeilenargument hinzufügen, das als Schalter zwischen einem automatischen Modus mit Standardwerten und dem vollständigen Benutzereingabemodus dient.

Wenn Sie eine bestimmte Interpretation Ihrer Anfrage verwenden, wird es ziemlich trivial. In diesem Modell wird der Benutzer zur Eingabe aufgefordert. Wenn sie nach einer Zeitüberschreitung nichts eingeben, wird der Standardwert verwendet. Wenn sie etwas eingeben, wird kein Timeout verwendet. Diese befasst sich auch mit der Nutzbarkeit Ausgabe des Aufgebens und einen Standardwert zu verwenden, wenn sie eine lange Zeit nimmst in etwas zu geben.

static void Main(string[] args) 
    { 
     Console.WriteLine("Please enter your name "); 
     string input; 

     if (TryReadLine(out input, 10000, true)) 
     { 
      Console.WriteLine(input); 
     } 
     else 
     { 
      Console.WriteLine("[DEFAULT]"); 
     } 

     Console.ReadKey(true); 
    } 

    const string timerString = "[{0} seconds until default value is used]"; 

    public static bool TryReadLine(out string s, double timeout, bool showTimer) 
    { 
     DateTime timeoutDateTime = DateTime.Now.AddMilliseconds(10000); 
     DateTime nextTimer = DateTime.Now; 
     while (DateTime.Now < timeoutDateTime) 
     { 
      if (Console.KeyAvailable) 
      { 
       ClearTimer(timeoutDateTime); 
       s = Console.ReadLine(); 
       return true; 
      } 

      if (showTimer && DateTime.Now > nextTimer) 
      { 
       WriteTimer(string.Format(timerString, (timeoutDateTime - DateTime.Now).Seconds)); 
       nextTimer = DateTime.Now.AddSeconds(1); 
      } 
     } 

     ClearTimer(timeoutDateTime); 
     s = null; 
     return false; 
    } 

    private static void ClearTimer(DateTime timeoutDateTime) 
    { 
     WriteTimer(new string(' ', string.Format(timerString, (timeoutDateTime - DateTime.Now).Seconds).Length)); 
    } 

    private static void WriteTimer(string s) 
    { 
     int cursorLeft = Console.CursorLeft; 
     Console.CursorLeft = 0; 
     Console.CursorTop += 1; 
     Console.Write(s); 
     Console.CursorLeft = cursorLeft; 
     Console.CursorTop -= 1; 
    } 
} 

Weil ich auf sie so lange verbringen, bevor ich es realisiert war ein besserer Weg , hier ist ein Code, den ich gerade angeschlagen habe, um eine Zeichenfolge von der Konsole mit einer Zeitüberschreitung zu lesen. Es hat auch die Möglichkeit, die aktuelle Zeit auf der Konsole zu drucken. Es ist nicht sehr gründlich getestet, so dass es wahrscheinlich viele Bugs gibt. Die Callback-Funktion verwendet die .NET 3.0-Aktion. Wenn dies jedoch für C# 2.0 gilt, können Sie sie einfach in einen Delegaten umwandeln.

static void Main(string[] args) 
    { 
     string input; 
     Console.Write("Please enter your name ("); 
     int timerPromptStart = Console.CursorLeft; 
     Console.Write(" seconds left): "); 
     if (TryReadLine(out input, 10000, delegate(TimeSpan timeSpan) 
              { 
               int inputPos = Console.CursorLeft; 
               Console.CursorLeft = timerPromptStart; 
               Console.Write(timeSpan.Seconds.ToString("000")); 
               Console.CursorLeft = inputPos; 
              }, 
              1000)) 
     { 
      Console.WriteLine(input); 
     } 
     else 
     { 
      Console.WriteLine("DEFAULT"); 
     } 
     while (true) { } 
    } 

    /// <summary> 
    /// Tries to read a line of input from the Console. 
    /// </summary> 
    /// <param name="s">The string to put the input into.</param> 
    /// <param name="timeout">The time in milliseconds before the attempt fails.</param> 
    /// <returns>Whether the user inputted a line before the timeout.</returns> 
    public static bool TryReadLine(out string s, double timeout) 
    { 
     return TryReadLine(out s, timeout, null, 0); 
    } 

    /// <summary> 
    /// Tries to read a line of input from the Console. 
    /// </summary> 
    /// <param name="s">The string to put the input into.</param> 
    /// <param name="timeout">The time in milliseconds before the attempt fails.</param> 
    /// <param name="timerCallback">A function to call every callbackInterval.</param> 
    /// <param name="callbackInterval">The length of time between calls to timerCallback.</param> 
    /// <returns>Whether the user inputted a line before the timeout.</returns> 
    public static bool TryReadLine(out string s, double timeout, Action<TimeSpan> timerCallback, double callbackInterval) 
    { 
     const int tabLength = 6; 

     StringBuilder inputBuilder = new StringBuilder(); 
     int readStart = Console.CursorLeft; 
     int lastLength = 0; 
     bool isInserting = true; 
     DateTime endTime = DateTime.Now.AddMilliseconds(timeout); 
     DateTime nextCallback = DateTime.Now; 
     while (DateTime.Now < endTime) 
     { 
      if (timerCallback != null && DateTime.Now > nextCallback) 
      { 
       nextCallback = DateTime.Now.AddMilliseconds(callbackInterval); 
       timerCallback((endTime - DateTime.Now)); 
      } 

      if (Console.KeyAvailable) 
      { 
       ConsoleKeyInfo key = Console.ReadKey(true); 
       switch (key.Key) 
       { 
        case ConsoleKey.Enter: 
         Console.WriteLine(); 
         s = inputBuilder.ToString(); 
         return true; 

        case ConsoleKey.Backspace: 
         if (Console.CursorLeft > readStart) 
         { 
          Console.CursorLeft -= 1; 
          inputBuilder.Remove(Console.CursorLeft - readStart, 1); 
         } 
         break; 

        case ConsoleKey.Delete: 
         if (Console.CursorLeft < readStart + inputBuilder.Length) 
         { 
          inputBuilder.Remove(Console.CursorLeft - readStart, 1); 
         } 
         break; 

        case ConsoleKey.Tab: 
         // Tabs are very difficult to handle properly, so we'll simply replace it with spaces. 
         AddOrInsert(inputBuilder, new String(' ', tabLength), isInserting, readStart); 
         Console.CursorLeft += tabLength; 
         break; 

        case ConsoleKey.Escape: 
         Console.CursorLeft = readStart; 
         inputBuilder = new StringBuilder(); 
         break; 

        case ConsoleKey.Insert: 
         isInserting = !isInserting; 
         // This may be dependant on a variable somewhere. 
         if (isInserting) 
         { 
          Console.CursorSize = 25; 
         } 
         else 
         { 
          Console.CursorSize = 50; 
         } 
         break; 

        case ConsoleKey.Home: 
         Console.CursorLeft = readStart; 
         break; 

        case ConsoleKey.End: 
         Console.CursorLeft = readStart + inputBuilder.Length; 
         break; 

        case ConsoleKey.LeftArrow: 
         if (Console.CursorLeft > readStart) 
         { 
          Console.CursorLeft -= 1; 
         } 
         break; 

        case ConsoleKey.RightArrow: 
         if (Console.CursorLeft < readStart + inputBuilder.Length) 
         { 
          Console.CursorLeft += 1; 
         } 
         break; 

        case ConsoleKey.UpArrow: 
         // N.B. We can't handle Up like we normally would as we don't know the last console input. 
         //  You might want to handle this so it works appropriately within your own application. 
         break; 

        case ConsoleKey.PageUp: 
        case ConsoleKey.PageDown: 
        case ConsoleKey.PrintScreen: 
        case ConsoleKey.LeftWindows: 
        case ConsoleKey.RightWindows: 
        case ConsoleKey.Sleep: 
        case ConsoleKey.F1: 
        case ConsoleKey.F2: 
        case ConsoleKey.F3: 
        case ConsoleKey.F4: 
        case ConsoleKey.F5: 
        case ConsoleKey.F6: 
        case ConsoleKey.F7: 
        case ConsoleKey.F8: 
        case ConsoleKey.F9: 
        case ConsoleKey.F10: 
        case ConsoleKey.F11: 
        case ConsoleKey.F12: 
        case ConsoleKey.F13: 
        case ConsoleKey.F14: 
        case ConsoleKey.F15: 
        case ConsoleKey.F16: 
        case ConsoleKey.F17: 
        case ConsoleKey.F18: 
        case ConsoleKey.F19: 
        case ConsoleKey.F20: 
        case ConsoleKey.F21: 
        case ConsoleKey.F22: 
        case ConsoleKey.F23: 
        case ConsoleKey.F24: 
        case ConsoleKey.BrowserBack: 
        case ConsoleKey.BrowserForward: 
        case ConsoleKey.BrowserStop: 
        case ConsoleKey.BrowserRefresh: 
        case ConsoleKey.BrowserSearch: 
        case ConsoleKey.BrowserFavorites: 
        case ConsoleKey.BrowserHome: 
        case ConsoleKey.VolumeMute: 
        case ConsoleKey.VolumeUp: 
        case ConsoleKey.VolumeDown: 
        case ConsoleKey.MediaNext: 
        case ConsoleKey.MediaPrevious: 
        case ConsoleKey.MediaStop: 
        case ConsoleKey.MediaPlay: 
        case ConsoleKey.LaunchMail: 
        case ConsoleKey.LaunchMediaSelect: 
        case ConsoleKey.LaunchApp1: 
        case ConsoleKey.LaunchApp2: 
        case ConsoleKey.Play: 
        case ConsoleKey.Zoom: 
        case ConsoleKey.NoName: 
        case ConsoleKey.Pa1: 
         // These keys shouldn't do anything. 
         break; 

        case ConsoleKey.Clear: 
        case ConsoleKey.Pause: 
        case ConsoleKey.Select: 
        case ConsoleKey.Print: 
        case ConsoleKey.Execute: 
        case ConsoleKey.Process: 
        case ConsoleKey.Help: 
        case ConsoleKey.Applications: 
        case ConsoleKey.Packet: 
        case ConsoleKey.Attention: 
        case ConsoleKey.CrSel: 
        case ConsoleKey.ExSel: 
        case ConsoleKey.EraseEndOfFile: 
        case ConsoleKey.OemClear: 
         // I'm not sure what these do. 
         break; 

        default: 
         Console.Write(key.KeyChar); 
         AddOrInsert(inputBuilder, key.KeyChar.ToString(), isInserting, readStart); 
         break; 
       } 

       // Write what has current been typed in back out to the Console. 
       // We write out everything after the cursor to handle cases where the current input string is shorter than before 
       // (i.e. the user deleted stuff). 
       // There is probably a more efficient way to do this. 
       int oldCursorPos = Console.CursorLeft; 
       Console.CursorLeft = readStart; 
       Console.Write(inputBuilder.ToString()); 
       if (lastLength > inputBuilder.Length) 
       { 
        Console.Write(new String(' ', lastLength - inputBuilder.Length)); 
       } 
       lastLength = inputBuilder.Length; 
       Console.CursorLeft = oldCursorPos; 
      } 
     } 

     // The timeout period was reached. 
     Console.WriteLine(); 
     s = null; 
     return false; 
    } 

    // This is a rather ugly helper method to add text to the inputBuilder, either inserting or appending as appropriate. 
    private static void AddOrInsert(StringBuilder inputBuilder, string s, bool insert, int readStart) 
    { 
     if (Console.CursorLeft < readStart + inputBuilder.Length + (insert ? -1 : 1)) 
     { 
      if (!insert) 
      { 
       inputBuilder.Remove(Console.CursorLeft - 1 - readStart, 1); 
      } 
      inputBuilder.Insert(Console.CursorLeft - 1 - readStart, s); 
     } 
     else 
     { 
      inputBuilder.Append(s); 
     } 
    } 
} 
Verwandte Themen