¿a qué se debe que el timer en winforms sea poco exacto?

Iniciado por Bengalaa, 22 Abril 2010, 16:37 PM

0 Miembros y 1 Visitante están viendo este tema.

Bengalaa

Saludos foreros...

Estoy haciendo una aplicación en .Net que mide el tiempo de reacción de un individuo, es para una tésis, así que necesito que la información sobre el tiempo sea muy exacta.

Así que agregué un timer en una winform, y lo programé, para que en el evento Tick, le sumara 1 a la variable Milisegundos, y lo escribiera en un label, dividido entre 100 y redondeado a 3 decimales. Así:

Option Explicit On
Option Strict On
Imports System.Math
Imports System.Data.OleDb

Public Class Form1
   Public Milisegundos As Integer

   Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
       Milisegundos = Milisegundos + 1

       LblTiempoTot.Text = Round(Milisegundos / 100, 3).ToString
       'LblTiempoTot.Text = Milisegundos.ToString

   End Sub
End Class


La propiedad Interval del Timer1 es 1.

El problema es:

Heché a andar el programa, y comparé la Label del tiempo, con los segundos del reloj de Windows; y TAN! es inexacto.

Resulta que tarda 2 segundos a veces... pero, a veces, el cambio lo hace exacto, y es muy inestable.

Ésto solo pasa cuando uso ese sistema, de milisegundos; intenté cambiar el intervalo a 1000, y no lo dividí ni lo redondeé, y me resulta muy exacto.

¿A qué se debe ésto? (debo resaltar que mi compu tiene una horrible RAM de 512 MB) si es por la RAM, cuál es el requerimiento necesario para que el timer sea exacto?

Les agredeceré un montón su ayuda  :D




P.S: saludos! ya que es mi primer post, espero seguir colaborando ^_^

----modifico----
otra cosita más... si se puede saber (o tengo que abrir otra pregunta en VB6?) VB6 necesitaría menos recursos?

Keyen Night

#1
Bueno tienes razón la exactitud es nula y respecto a la RAM no es ese el problema pues yo tengo 4Gb e igual pasa el problema.

Allí está esa diferencia de tiempo es la que tarda la aplicación en realizar las tareas que le asignastes en el sub del timer...
La Fé Mueve Montañas...
                                    ...De Dinero

La programación es más que un trabajo es más que un hobby es una pasión...

Atrum

Lo que sucede es que el evento Tick realiza lo que tienes en tu Sub y no es asincrono, eso quere decir que los ticks no continuan hasta que termina de hacer lo que tienes en tu evento:

Código (vbnet) [Seleccionar]

        Milisegundos = Milisegundos + 1

        LblTiempoTot.Text = Round(Milisegundos / 100, 3).ToString
        'LblTiempoTot.Text = Milisegundos.ToString


Asi que esto es lo que te podria generar la inecrtidumbre, y si tu maquina es lenta o esta cargada de transacciones pues los procedimientos pueden tardar mas, asi que yo te sugeriria que utilizaras un Stopwatch que es un simple objeto cronometro, te dejo un ejemplo con dos botones y un label:

Código (vbnet) [Seleccionar]

Public Class Form1

    Private stopw As New Stopwatch 'Creo mi nuevo stopwatch

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Timer1.Interval = 1 'declaro intervalo en 1
        Timer1.Start() 'inicio el timer
        stopw.Start() 'Inicio el stopwatch, aqui es donde empieza a contar el tiempo
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        'Aqui imprimo el valor de los minutos,segundos y milisegundos del stopwatch
        'mientras este sigue avanzando sin interrupciones
        Label1.Text = stopw.Elapsed.Minutes.ToString & " : " _
        & stopw.Elapsed.Seconds.ToString & " : " _
        & stopw.Elapsed.Milliseconds.ToString
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        'Con este boton detengo el timer y el stopwatch
        stopw.Stop()
        Timer1.Stop()
    End Sub

End Class


Bueno, pues espero que esto te sirva para tu proyecto, Suerte

Bengalaa

Gracias Keyen Night! gracias Xtriker!! me sirvió un montón XD

dejo el código final:

Public Class Form1
    Public ElCronometro As New Stopwatch

    Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick
        Dim MiliSegundos As Long = _
            ElCronometro.ElapsedMilliseconds
        LblTiempoTot.Text = Round(MiliSegundos / 1000, 4).ToString
    End Sub

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        ElCronometro.Start()
    End Sub

End Class



Ustedes son épicos, estaba arruinada con ésto del timer @.@'