2008-10-17 2 views
8

콘솔에서 입력을 요청하고 몇 초 동안 기다리면 몇 가지 값을 기본값으로 설정해야 할 수도 있습니다. 기본적으로 C#에서 콘솔 입력 시간을 측정하고 기본 설정을 계속 진행할 수 있습니까? 당신이 위대한 것입니다 샘플 코드가 있다면.콘솔 입력을 C#에서 15 초 동안 기다리는 방법

+0

"etc"로 태그하면 안됩니다. 그것은 꽤 의미가 없으므로 나는 C#으로 그것을 즐겼다. – Mark

+0

그리고 "기다려라"는별로 좋지 않습니다. 더 적절한 태그를 추가했습니다. –

+1

가능한 복제본 [Console.ReadLine()에 시간 제한을 추가하는 방법] (http://stackoverflow.com/questions/57615/how-to-add-a-timeout-to-console-readline) –

답변

0

한 가지 방법은 Console.In.Peek()을 호출하여 입력을 기다리거나 이동할 시간을 기다리는 것입니다.

2

here을 참조하십시오. 콘솔에서 멋진 작은 폴링 기술을 사용합니다.

3

System.Timers.Timer에서 타이머 개체를 사용하고 60 초로 설정하고 활성화하고 누군가가 콘솔에 무언가를 입력하면 사용하지 않도록 설정 한 다음 타이머에서 발생하는 상황을 처리 할 수 ​​있습니다 .Elapsed 행사.

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; 

     } 

이것이 최선의 방법인지 확실하지 않습니다. 나는 이것을 테스트했지만 내가 말했듯이 그것은 최선의 방법이 아닐 수도있다.

+3

문제가 이 모델의 경우 ReadLine은 회선이 입력 될 때까지 리턴하지 않는 차단 호출이므로 타이머가 경과 할 때 기본값이 전송되는 반면 프로그램은 텍스트가 입력 될 때까지 계속되지 않습니다. – ICR

+0

음, 네, 정말 그렇게 생각하지 않았습니다. 도청 전문가 –

2

기본값을 사용하는 자동 모드와 전체 사용자 입력 모드 사이를 전환하는 명령 줄 인수 추가와 같은 작업을 수행하는 것이 좋습니다.

요청에 대한 구체적인 해석을 사용하면 매우 사소 해집니다. 이 모델에서 사용자는 입력을 요구받습니다. 시간 종료 후에 아무 것도 입력하지 않으면 기본값이 사용됩니다. 입력이 시작되면 시간 초과가 사용되지 않습니다. 이것은 또한 포기하고 그들이 뭔가를 입력하는 데 시간이 오래 복용하고 기본값을 사용하는 사용성 문제를 다룹니다.

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

내가 더 나은 방법이 깨달았다 전에 그것에 너무 오래 지출 때문에 , 여기에 콘솔에서 문자열을 읽으려고 시도한 코드가 있습니다. 시간 초과가 있습니다. 또한 콘솔에 남아있는 현재 시간을 인쇄 할 수있는 옵션도 있습니다. 매우 철저하게 테스트되지 않았기 때문에 많은 버그가있을 수 있습니다. 콜백 기능은 .NET 3.0 액션을 사용합니다. C# 2.0 용이라면 델리게이트로 바꿀 수 있습니다.

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); 
     } 
    } 
} 
관련 문제