System::Threading::Timer einen Parameter übergeben



  • Hallo, ich möchte Messwerte erfassen und das bspw. zyklisch alle 100ms. Zu erst habe ich einen Thread erzeugt und dann über die Klasse Stopwatch die verbrauchte Zeit bestimmt. Danach habe ich mittels System::Threading::Sleep(x) die Differenz abgewartet. Doch nun habe ich mitbekommen, dass Sleep teilweise bis zu +- 8-9 ms schwankt.

    Daher wollte ich einen Timer verwenden. Jedoch ist es erforderlich, dass ein Objekt der Callback übergeben wird. Bei der Thread Geschichte war es ja über Parameterized Thread möglich ein Objekt zu übergeben.

    Wie kann ich das denn bei System::Threading::Timer machen? Ein Minimalbeispiel würde mir da schon sehr weiter helfen.

    Mfg Melexis



  • Benutze eine Member Variable.
    Simon



  • Ich habe das Problem jetzt so gelöst:

    System::Void Clickmethode(void)
    {
    ...
      TimerCallback^ timerDelegate = gcnew TimerCallback(  this ,  &Tool_Main::ContinMeasurementTimer);
    
      timer = gcnew System::Threading::Timer(timerDelegate, (Object^) s , 250 , 1000);
    }
    

    Was mich verwundert, wenn ich den Timer in der Click Methode des Measure Buttons deklariere und initialisiere dann stoppt die Messung irgendwann. Deklariere ich den Timer im Header und führe in der Click Methode den obigen Code aus, dann läuft der Timer 😮

    Kann es sein, dass der Garbage Collector den Speicher an dieser Stelle freischaufelt.



  • Kann es sein, dass der Garbage Collector den Speicher an dieser Stelle freischaufelt.

    Ja.
    Vermutlich "rootet" sich ein System.Threading.Timer nicht automatisch. D.h. er wird irgendwann finalisiert. Und dass ein finalisierter Timer nichtmehr feuert, ist hoffentlich klar 🙂

    Kannst du aber einfach ausprobieren, indem du gleich nach dem Anlegen des Timers GC.Collect(2) aufrufst.



  • Melexis84 schrieb:

    Doch nun habe ich mitbekommen, dass Sleep teilweise bis zu +- 8-9 ms schwankt.

    Daher wollte ich einen Timer verwenden.

    Auch mit dem Timer kannst du nen Jitter im Millisekunden Bereich bekommen Windows ist halt kein Echtzeitbetriebsystem wo garantiert werden kann das nach 100ms die Methode ausgeführt wird.



  • Hallo, danke für die Antwort.

    hustbaer schrieb:

    Kann es sein, dass der Garbage Collector den Speicher an dieser Stelle freischaufelt.

    Ja.
    Vermutlich "rootet" sich ein System.Threading.Timer nicht automatisch. D.h. er wird irgendwann finalisiert. Und dass ein finalisierter Timer nichtmehr feuert, ist hoffentlich klar 🙂

    Gibt es eine Möglichkeit diesen Umstand zu ändern? Oder muss ich die Instanz vom Timer im Header deklarieren?

    Kannst du aber einfach ausprobieren, indem du gleich nach dem Anlegen des Timers GC.Collect(2) aufrufst.

    Was bewirkt denn GC.Collect(2) denn?

    MFG



  • Melexis84 schrieb:

    Hallo, danke für die Antwort.

    hustbaer schrieb:

    Kann es sein, dass der Garbage Collector den Speicher an dieser Stelle freischaufelt.

    Ja.
    Vermutlich "rootet" sich ein System.Threading.Timer nicht automatisch. D.h. er wird irgendwann finalisiert. Und dass ein finalisierter Timer nichtmehr feuert, ist hoffentlich klar 🙂

    Gibt es eine Möglichkeit diesen Umstand zu ändern? Oder muss ich die Instanz vom Timer im Header deklarieren?

    Natürlich gibt es keine Möglichkeit das zu ändern 🙄
    Du kannst den Timer selbst rooten, bloss das halte ich für eine ziemlich dämliche Idee.
    Die naheliegende Variante wäre ein Member zu verwenden.

    Kannst du aber einfach ausprobieren, indem du gleich nach dem Anlegen des Timers GC.Collect(2) aufrufst.

    Was bewirkt denn GC.Collect(2) denn?

    Lies es bloss nicht in der MSDN nach!!!



  • Warum denn auch? Hab euch Volldeppen doch...



  • Melexis84 schrieb:

    Warum denn auch? Hab euch Volldeppen doch...

    Sorry dieser sinnlos Post ist nicht von mir! Ok da werde ich mal spassenshalber GC.collect ausprobieren 😃



  • Melexis84 schrieb:

    Melexis84 schrieb:

    Warum denn auch? Hab euch Volldeppen doch...

    Sorry dieser sinnlos Post ist nicht von mir!

    oben rechts ist eine Registrierungs-Link ... nutze ihn einfach



  • Naja solche Kinder die sich mit ihren unqualifizierten Äußerungen outen hat man immer wieder 🙄 Oder es liegt vielleicht daran, dass sie hier nichts verstehen...

    ----------------
    Wie dem auch sei, ich habe jetzt mal Timers::Timer und Threading::Timer verwendet. Und mitbekommen, dass bei Intervallen unter einer halben Sekunde eine relativ große Ungenauigkeit hinein kommt.

    Wenn ich bspw. jede Sekunde den Timer ticken lasse, dann passt das ganze bis auf die Millisekunde laut Datetime::Now aber sobald ich das Intervall kleiner mache, schleicht sich ein Fehler ein. Bei 100ms Intervall wird erst 109-110ms nach dem letzten ::Now aufruf die Zeit aufgenommen. Bei 200ms ist man bei 205-207ms drüber.

    Ich bin mir ja im klaren, dass Windows kein Echtzeitsystem ist. Was mich aber verwundert ist die Tatsache, dass der darauffolgende Wert immer um diese Verzögerung bestimmt wird. Sprich der Wert 4 ist ebenso 109-110ms später als der 3. Genauso verhält sich der 400. zum 399..

    Bei beiden Timern tritt das gleiche Phänomen auf. Ich mach in der Tickmethode einfach nur

    Debug::Writeline(DateTime::Now.ToString("hh🇲🇲ss.fff")

    Existiert denn eine Möglichkeit, dass der Fehler noch minimiert werden kann?

    MFG





  • stellt sich mir die Frage ob es überhaupt Sinnmacht diesen Timer zu verwenden ... bisher habe ich den noch nie benötigt ... und die paar Millisekunden Abweichung 🕶



  • Existiert denn eine Möglichkeit, dass der Fehler noch minimiert werden kann?

    Was willst du denn eigentlich machen?



  • hustbaer schrieb:

    Existiert denn eine Möglichkeit, dass der Fehler noch minimiert werden kann?

    Was willst du denn eigentlich machen?

    Naja ich habe einen Timer, bei dem zyklisch alle bspw. 15ms ein Messwert abgefragt werden soll. Bevor der Timer gestartet wird kann der Anwender in einem numerischen Feld angeben in welchem Intervall diese Messung ausgelöst werden soll.



  • Mexlexis84 schrieb:

    hustbaer schrieb:

    Existiert denn eine Möglichkeit, dass der Fehler noch minimiert werden kann?

    Was willst du denn eigentlich machen?

    Naja ich habe einen Timer, bei dem zyklisch alle bspw. 15ms ein Messwert abgefragt werden soll. Bevor der Timer gestartet wird kann der Anwender in einem numerischen Feld angeben in welchem Intervall diese Messung ausgelöst werden soll.

    öhm ... macht das Sinn das das so oft abgefragt wird?? ... wenn ja solltest Du über eine Hardwarelösung nachdenken die abfragt und zwischen speichert ... die Zwischenspeicherung kannst Du dann ja mit Deinem Programm alle 1000 ms abrufen

    hand, mogel

    PS: AFAIK hat Windows eine Auflösung von 16ms mit einem Contextwechsel


Anmelden zum Antworten