2009-07-23 10 views
14

Estoy tratando de hacer que un temporizador marque una vez por segundo en un winform, cuando busco consejos sobre cómo hacerlo encuentro muchas cosas sobre los hilos. Bueno, no me importan los hilos, porque todo lo que intento hacer es hacer un conteo regresivo de 60 a 0 en un minuto, luego parar. No creo que tengamos que recurrir a la computación en la nube para resolver este problema, pero en realidad soy un organismo de formularios web, por lo que estoy un poco oxidado sobre este tema. ¿Puede alguien que me señale un ejemploWinforms Timer for Dummies

Esto es lo que he intentado

private void button1_Click(object sender, EventArgs e) 
    { 
     this.timeLeft = 60; 
     this.label1.Visible = false; 
     this.button1.Visible = false; 
     gt = new Timer(); 
     gt.Tick += new EventHandler(CountDown); 
     gt.Interval = 1000; 
     gt.Start(); 
    } 

private void CountDown(object sender, EventArgs e) 
{ 
    do 
    { 
     this.TimeBar.Value = timeLeft;     
     this.timeLeft -= 1; 
    } while (this.timeLeft > 0); 
    if (this.TimeBar.Value > 0) return; 
    gt.Stop(); 
    this.label1.Visible = true; 
    this.button1.Visible = true; 
} 

Cualquier ayuda sería muy apreciada.

Respuesta

8

Lo que está sucediendo es que está disminuyendo la variable timeLeft hasta que llega a cero en el primer tic del temporizador. Saca el bucle do...while y tendrías un ejemplo básicamente funcional.

Sin embargo, si va a hacer cualquier cantidad de trabajo de Windows Forms, debe aprender a enhebrar y cómo eso afecta la interfaz de usuario. Rápidamente se encontrará de nuevo aquí si no lo hace con historias de excepciones inútiles y componentes de UI que se comportan mal. Jon Skeet tiene un excelente threading series. Lo recomiendo altamente. Tiene una sección dedicada a los temporizadores, por lo que podría darle una idea adicional.

+0

Y no olvide deshabilitar el temporizador después de que la cuenta regresiva haya terminado, de lo contrario, se encontrará con números negativos. –

+0

Gracias, es bastante tarde aquí, por supuesto que no necesito el loop, doh! Gracias también por el enlace a los documentos de enhebrado del Sr. Skeet. :) –

+0

@Martinho - Obligado, sí, eso me tiene a mí también :) –

8

Usted no necesita enhebrar si utiliza el temporizador de winforms.

Caída de un control Timer en su página, el nombre de "temporizador" y pegue el siguiente código:

public MainForm() 
{ 
    InitializeComponent(); 

    timer.Interval = 1000; 
    timer.Start(); 

    timeLeft = 60; 
    timer.Tick += Timer_Tick; 

    // start things 
    label1.Hide(); 
    button1.Hide(); 
    timer.Start(); 

} 

public void Timer_Tick(object sender, EventArgs e) 
{ 
    timeLeft--; 

    if (timeLeft <= 0) { 
     timer.Stop(); 
     label1.Show(); 
     button1.Show(); 
    } 
} 

supongo que si has venido de un fondo Webby, programación de eventos impulsados ​​es probablemente la cosa necesita comenzar a leer si quiere saber cómo están programadas las cosas en los escritorios.

+0

Gracias, sí, el enhebrado fue solo ruido, lo tengo ordenado ahora, pero también tengo algunos buenos consejos de lectura. –

2

No desea hacer ningún bucle en su controlador de eventos. El controlador se llama una vez por temporizador 'tick' - cada 1000 milisegundos, como lo haya configurado. Por lo tanto, desea disminuir su variable timeLeft una vez por llamada, luego cerrar todo cuando timeLeft llegue a cero.

// untested 
private void CountDown(object sender, EventArgs e) 
{ 
    this.TimeBar.Value = timeLeft; 
    this.timeLeft--; 
    if (this.TimeBar.Value == 0) 
    { 
     gt.Stop(); 
     this.label1.Visible = true; 
     this.button1.Visible = true; 
    } 
} 
+0

Gracias, estaba teniendo un poco de desvanecimiento cerebral, haciendo un pequeño proyecto para mi hija, debido a la mala televisión aquí. Tu código es más o menos con lo que terminé. –

3

Aparte de sacar el bucle (según la respuesta de JasonH), su enfoque podría ser un poco impreciso si la aplicación es un poco ocupado. Aunque especifique su intervalo en milisegundos, los temporizadores de WinForms tienen una resolución de 18 ms y tienen una prioridad muy baja, el ciclo de mensajes solo verifica los temporizadores si no encuentra nada más que hacer.

Por lo tanto, mantenga un valor StartTime (DateTime) y utilícelo para calcular el tiempo restante en cada evento Timer. Solo podría necesitar 61 tics para llegar a un minuto.

+0

Sí, el temporizador tiene una precisión de aproximadamente 55 ms que leo. Solo está haciendo algo realmente trivial, por lo que + -3 segundos en un minuto funcionarán, los otros procesos tampoco romperán el banco. Gracias, sin embargo :) –