Pregunta

Estoy tratando de reconstruir una vieja metrónomo aplicación que fue escrito originalmente el uso de MFC en C++ para ser escrita .NET usando C#.Uno de los problemas que me estoy quedando en es conseguir que el temporizador para "marcar" con la suficiente precisión.

Por ejemplo, suponiendo una fácil BPM (beats por minuto) de 120, el temporizador debe marcar cada .5 segundos (o 500 milisegundos).Utilizando esto como base para las garrapatas, sin embargo, no es del todo exacto como .NET sólo garantiza que el temporizador no se garrapatas antes de que el tiempo transcurrido ha pasado.

En la actualidad, para conseguir alrededor de esto, para el mismo 120 BPM ejemplo utilizado anteriormente, estoy configurando las garrapatas a algo así como 100 milisegundos y jugando sólo el sonido de clic sobre cada 5 temporizador de intervalo.Esto mejora la precisión de un poco, pero si se siente como un poco de un hack.

Así que, ¿cuál es la mejor manera de obtener información correcta de las garrapatas?Sé que hay más temporizadores disponibles de los que el temporizador de windows forms que ya está disponible en Visual Studio, pero yo no estoy muy familiarizado con ellos.

¿Fue útil?

Solución

Hay tres clases timer llamado 'Contador' en .NET.Suena como que usted está utilizando Windows Forms uno, pero en realidad, usted puede encontrar el Sistema.Las operaciones de roscado.Temporizador de clase más útil - pero tenga cuidado, porque las llamadas en una piscina, de hilo, de modo que no puede interactuar directamente con su forma de la devolución de llamada.

Otro enfoque podría ser p/invoke para el Win32 multimedia temporizadores - timeGetTime, timeSetPeriod, etc.

Una rápida en google y encontré esto, que podría ser útil http://www.codeproject.com/KB/miscctrl/lescsmultimediatimer.aspx

'Multimedia' (timer) es la palabra de moda para buscar en este contexto.

Otros consejos

¿Cuál es la aplicación de C++ usando?Usted puede utilizar siempre la misma cosa o envuelva el temporizador de código de C++ en C++/CLI clase.

He tenido este problema al desarrollar un reciente registro de datos del proyecto.El problema con el .NET temporizadores ( de windows.formularios del sistema.roscado y sistema.timer ) es que son sólo precisa hasta alrededor de 10 mili segundos que es debido a la programación de eventos construido en .NETA que yo creo.( Estoy hablando .NET 2 aquí ).Esto no era aceptable para mí y tuve que usar el temporizador multimedia ( es necesario importar el archivo dll ).También escribí una clase de contenedor para todos los temporizadores y así que usted puede cambiar entre ellos si es necesario con cambios mínimos en el código.Echa un vistazo a mi blog aquí:http://www.indigo79.net/archives/27

Otra posibilidad es que hay un error en la aplicación de WPF DispatcherTimer (hay un desajuste entre milisegundos y garrapatas potencial de causar inexactitud dependiendo de proceso exacto el tiempo de ejecución) , como se evidencia a continuación:

http://referencesource.microsoft.com/#WindowsBase/Base/System/Windows/Threading/DispatcherTimer.cs,143

class DispatcherTimer
{
    public TimeSpan Interval
    {
        set
        {
            ...
            _interval = value;
            // Notice below bug: ticks1 + milliseconds [Bug1]
            _dueTimeInTicks = Environment.TickCount + (int)_interval.TotalMilliseconds;
        }
    }
}

http://referencesource.microsoft.com/#WindowsBase/Base/System/Windows/Threading/Dispatcher.cs

class Dispatcher
{
    private object UpdateWin32TimerFromDispatcherThread(object unused)
    {
        ...
        _dueTimeInTicks = timer._dueTimeInTicks;
        SetWin32Timer(_dueTimeInTicks);
    }

    private void SetWin32Timer(int dueTimeInTicks)
    {
        ...
        // Notice below bug: (ticks1 + milliseconds) - ticks2  [Bug2 - almost cancels Bug1, delta is mostly milliseconds not ticks]
        int delta = dueTimeInTicks - Environment.TickCount; 
        SafeNativeMethods.SetTimer( 
            new HandleRef(this, _window.Value.Handle),
            TIMERID_TIMERS,
            delta); // <-- [Bug3 - if delta is ticks, it should be divided by TimeSpan.TicksPerMillisecond = 10000]
    }
}

http://referencesource.microsoft.com/#WindowsBase/Shared/MS/Win32/SafeNativeMethodsCLR.cs,505

class SafeNativeMethodsPrivate
{
    ...
    [DllImport(ExternDll.User32, SetLastError = true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)]
    public static extern IntPtr SetTimer(HandleRef hWnd, int nIDEvent, int uElapse, NativeMethods.TimerProc lpTimerFunc);
}

http://msdn.microsoft.com/en-us/library/windows/desktop/ms644906%28v=vs.85%29.aspx

uElapse [in]
Type: UINT
The time-out value, in milliseconds. // <-- milliseconds were needed eventually

Temporizador de clases puede empezar a comportarse de manera extraña cuando el temporizador de 'marca' código de evento no ha terminado de ejecutar por la hora de la próxima 'marca' se produce.Una forma de combatir esto es para desactivar el temporizador en el comienzo del evento tick, a continuación, volver a habilitar al final.

Sin embargo, este enfoque no es adecuado en los casos donde el tiempo de ejecución de la 'marca', el código no es aceptable de error en el momento de la garrapata, ya que el temporizador estará desactivado (no se cuenta) durante ese tiempo.

Si al deshabilitar el temporizador es una opción, entonces usted también puede conseguir el mismo efecto mediante la creación de un subproceso independiente que se ejecuta, se duerme durante x milisegundos, ejecuta, duerme, etc...

System.Windows.Forms.Timer se limita a una precisión de 55 milisegundos...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top