2008-10-17 12 views
8

Necesito pedir entrada en la consola y esperar unos pocos segundos puede ser un minuto después de eso tengo que establecer un valor predeterminado. ¿Cómo se puede, básicamente, sincronizar nuestra entrada de la consola en C# y continuar con la configuración predeterminada? Si tiene un código de muestra que sería genial.cómo espero en la entrada de la consola en C# durante 15 segundos o menos

+0

realmente no debería etiquetar cosas con "etc". No tiene sentido, así que lo puse con C#. – Mark

+0

Y "esperar" tampoco es muy bueno. Agregué más etiquetas apropiadas. –

+1

posible duplicado de [Cómo agregar un tiempo de espera a Console.ReadLine()?] (Http://stackoverflow.com/questions/57615/how-to-add-a-timeout-to-console-readline) –

Respuesta

0

Una forma sería hacer un bucle, llamando a Console.In.Peek(), esperando la entrada o el tiempo suficiente para hacerlo.

2

Ver here, utiliza una técnica de encuesta agradable en la consola, que aunque un poco crudo, muy efectivo.

3

Puede utilizar el objeto del temporizador en System.Timers.Timer y configurarlo en 60 segundos, habilitarlo y si alguien introduce algo en la consola simplemente desactívelo, de lo contrario, simplemente maneje lo que sucede en el Timer.Elapsed evento.

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; 

     } 

No estoy seguro de si esta es la mejor manera. He probado esto, pero como dije, puede que no sea la mejor manera.

+3

El problema con este modelo es que ReadLine es una llamada de bloqueo que no regresa hasta que se ingresó la línea, por lo tanto, aunque el valor predeterminado puede enviarse cuando el temporizador ha transcurrido, el programa no continuará hasta que se haya ingresado el texto. – ICR

+0

mmm sí, realmente no pensé en eso. Tío –

2

Es posible que desee considerar hacer algo así como agregar un argumento de línea de comando para actuar como un interruptor entre un modo automático que utiliza los valores predeterminados y el modo de entrada de usuario completo.

Si utiliza una interpretación específica de su solicitud, se vuelve bastante trivial. En este modelo, al usuario se le solicita una entrada. Si no escriben nada después de un período de tiempo de espera, se utiliza el valor predeterminado. Si comienzan a escribir algo, entonces no se utiliza el tiempo de espera. Esto también se ocupa del problema de usabilidad de dar y utilizar un valor predeterminado cuando se está tomando mucho tiempo para escribir algo en.

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; 
    } 
} 

porque paso tanto tiempo en él antes de que me di cuenta que había una manera mejor , aquí hay un código que acabo de pinchar para leer una cadena de la consola, con un tiempo de espera excedido. También tiene la opción de poder imprimir la hora actual que queda en la consola. No se ha probado muy a fondo, por lo que es probable que tenga muchos errores. La función de devolución de llamada utiliza la acción .NET 3.0, aunque si esto es para C# 2.0 puede convertirlo en un delegado.

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); 
     } 
    } 
} 
Cuestiones relacionadas