2012-08-02 19 views
8

Supongamos que mi programa de consola realiza varias tareas largas. Entre estas tareas, me gustaría hacer una pausa, ya sea por unos segundos o hasta que se presione cualquier tecla. (Lo que ocurra primero.)Esperar a Keypress (o) N segundos para caducar

Estos criterios son fáciles de comprobar por sí mismos, pero se niegan a llevarse bien cuando intento la combinación de ellos: O bien el mecanismo de sincronización se detiene durante unos segundos antes de ReadKey comienza, o bloques readkey cabo el hilo por completo hasta que esté satisfecho. ¿Cómo puedo satisfacer ambas condiciones?

+3

http://stackoverflow.com/questions/57615/how-to-add-a-timeout-to-console- readline – dugas

+0

¿Hay algún ejemplo disponible? Esto suena como si solo pudieras notificar al hilo principal que esto se hace, luego espera hasta que puedas continuar, realiza un seguimiento de cualquier temporizador y finalízalo si presionas el teclado, pero no puedes dar detalles sin el ejemplo –

Respuesta

15

Una forma de hacer esto en C# 4.0:

Task.Factory.StartNew(() => Console.ReadKey()).Wait(TimeSpan.FromSeconds(5.0)); 
+1

Si necesitas saber el fuente, luego solo guarde el resultado de la llamada 'Wait' a una variable bool. Si se agota el tiempo, se devolverá falso, de lo contrario se devolverá verdadero (lo que significa que hay una clave disponible). – SPFiredrake

+3

Debería haber agregado que probablemente solo deberías usar este enfoque para las aplicaciones de consola de vida corta que no tienen muchos pasos, ya que cada vez que se toma la ruta de "tiempo de espera agotado", habrá un hilo zombie esperando una clave prensa. ¡No intentes esto dentro de un bucle de 10,000 cuentas! – lesscode

+0

@Wayne Ese es un buen punto, no había pensado en eso. (Y sí planeo usarlo muchas veces) ¿Debo tomar alguna medida para evitar que se acumulen? – 4444

0

Comience dos hilos. Uno escucha la pulsación de tecla y otras esperas durante un tiempo. Haga que el hilo principal espere a menos que haya terminado. Luego proceda e ignore otra respuesta de subproceso. :)

3

Una forma de hacer esto es sin temporizador en absoluto. Cree un bucle que duerma el hilo por digamos 25 milisegundos, y luego verifique si se ha presionado una tecla a través de Console.KeyAvailable (que no es bloqueante), o hasta que el tiempo entre DateTime.Now() y el tiempo de inicio del bucle haya excedido el tiempo de espera .

+0

Esto no funcionará correctamente si la hora del sistema se cambia mientras el programa se está ejecutando, ¿lo hará? –

0

¿Algo como esto?

bool IsPaused; 
bool IsKeyPaused; 

void Pause(){} 
void UnPause(){} 

void KeyDown(){ 
    if(!IsPaused) 
    { 
     IsPaused = true; 
     IsKeyPaused = true; 
     Pause(); 
    } 
} 
void KeyUp(){ 
    if(IsKeyPaused) 
    { 
     IsPaused = false; 
     IsKeyPaused = false; 
     UnPause(); 
    } 
} 
void TimerPause(){ 
    if(!IsPaused) 
    { 
     IsPaused = true; 
     Pause(); 
    } 
} 
void TimerEnd(){ 
    UnPause(); 
} 
2

La extensión de la respuesta de ikh que quería una cuenta atrás con la mía

 var original = DateTime.Now; 
     var newTime = original; 

     var waitTime = 10; 
     var remainingWaitTime = waitTime; 
     var lastWaitTime = waitTime.ToString(); 
     var keyRead = false; 
     Console.Write("Waiting for key press or expiring in " + waitTime); 
     do 
     { 
      keyRead = Console.KeyAvailable; 
      if (!keyRead) 
      { 
       newTime = DateTime.Now; 
       remainingWaitTime = waitTime - (int) (newTime - original).TotalSeconds; 
       var newWaitTime = remainingWaitTime.ToString(); 
       if (newWaitTime != lastWaitTime) 
       { 
        var backSpaces = new string('\b', lastWaitTime.Length); 
        var spaces = new string(' ', lastWaitTime.Length); 
        Console.Write(backSpaces + spaces + backSpaces); 
        lastWaitTime = newWaitTime; 
        Console.Write(lastWaitTime); 
        Thread.Sleep(25); 
       } 
      } 
     } while (remainingWaitTime > 0 && !keyRead); 
Cuestiones relacionadas