C#, Warum sind timer-Frequenzen extrem aus?

Beide System.Timers.Timer und System.Threading.Timer Feuer in Intervallen, sind erheblich Verschieden von der gewünschten diejenigen.
Zum Beispiel:

new System.Timers.Timer(1000d / 20);

ergibt sich ein timer löst 16-mal pro Sekunde, nicht 20.

Sicher sein, dass es gibt keine Nebenwirkungen von zu langen Ereignis-Handlern, schrieb ich dieses kleine test-Programm:

int[] frequencies = { 5, 10, 15, 20, 30, 50, 75, 100, 200, 500 };

//Test System.Timers.Timer
foreach (int frequency in frequencies)
{
    int count = 0;

    //Initialize timer
    System.Timers.Timer timer = new System.Timers.Timer(1000d / frequency);
    timer.Elapsed += delegate { Interlocked.Increment(ref count); };

    //Count for 10 seconds
    DateTime start = DateTime.Now;
    timer.Enabled = true;
    while (DateTime.Now < start + TimeSpan.FromSeconds(10))
        Thread.Sleep(10);
    timer.Enabled = false;

    //Calculate actual frequency
    Console.WriteLine(
        "Requested frequency: {0}\nActual frequency: {1}\n",
        frequency, count / 10d);
}

Die Ausgabe sieht wie folgt aus:

Angefordert: 5 Hz; aktuell: 4,8 Hz

Angefordert: 10 Hz; aktuell: 9,1 Hz

Angefordert: 15 Hz; aktuell: 12,7 Hz

Angefordert: 20 Hz; aktuell: 16 Hz

Angefordert: 30 Hz; aktuell: 21,3 Hz

Angefordert: 50 Hz; aktuell: 31,8 Hz

Beantragt: 75 Hz; aktuell: 63,9 Hz

Angefordert: 100 Hz; aktuell: 63,8 Hz

Angefordert: 200 Hz; aktuell: 63,9 Hz

Angefordert: 500 Hz; aktuell: 63,9 Hz

Der tatsächlichen Frequenz abweicht von bis zu 36% aus der angeforderte. (Und offenbar darf nicht mehr als 64 Hz.) Da Microsoft empfiehlt diese timer für die "höhere Genauigkeit" über System.Windows.Forms.Timer, das verwirrt mich.

Btw, diese sind nicht zufällige Abweichungen. Es sind die gleichen Werte jedes mal.
Und ein ähnliches test-Programm für die anderen timer-Klasse System.Threading.Timer, zeigt die exakt gleichen Ergebnisse.

In meinem eigentlichen Programm, ich brauche zu sammeln, die Messungen bei exakt 50 samples pro Sekunde. Sollte dies dennoch nicht benötigen eine real-time-system. Und es ist sehr frustrierend 32 samples pro Sekunde statt 50.

Irgendwelche Ideen?

@Chris:
Du hast Recht, die Intervalle scheinen alle ganzzahligen vielfachen von irgendwas um die 1/64th Sekunde. Btw, hinzufügen einen Thread.Sleep(...) in den event-handler nicht einen Unterschied machen. Das macht Sinn, gegeben, dass System.Threading.Timer den threadpool verwendet, so dass jedes Ereignis ausgelöst wird, auf einen freien thread.

  • Ich bin mir nicht sicher, dass: "Das darf doch nicht benötigen eine real-time-system." wahr sein kann, gegeben : "ich muss erfassen, Messungen bei genau 50 samples pro Sekunde."
  • Der MultiMediaTimer (winmm.dll) Nutzung vorgestellt von Justin Tanner funktioniert perfekt. Vielen Dank, Mann.
  • Ich bin damit einverstanden. Klingt wie eine harte Echtzeit-Anforderung zu mir - genau das, was ein RTOS gemeint ist, zu lösen. Veranstaltung alle 20ms mit einem guaranteeed Antwort von 1-2 ms.
  • Wenn Sie müssen "genau 50 samples pro Sekunde" Ihre beste Wette ist, um eine externe platine, mikrocontroller oder andere hardware, die Sie haben die Kontrolle über. Windows hat eine MENGE Los und Sie haben sehr begrenzte Kontrolle und Transparenz in den proprietären code.
InformationsquelleAutor Daniel Wolf | 2009-01-06
Schreibe einen Kommentar