Probleme mit Thread und XP/Vista



  • Morgen Zusammen...

    Ich hab ein kleines Problem mit meinem Programm.
    Ich hab einen Workersthread, der mehr oder weniger als Timer fungiert. Den Thread habe ich wie folgt gestartet:

    AfxBeginThread(ThreadFunc, _param, THREAD_PRIORITY_TIME_CRITICAL, 0, 0);
    

    Ich habe "THREAD_PRIORITY_TIME_CRITICAL" gewählt, weil ich im Bereich von 8ms Daten lese und schreibe (Logging eines externen Gerätes bei 125Hz). Das Programm läuft außer ein paar macken unter XP anstandslos. Die Macken sind in der Art wie, dass wenn der Therad gestartet wird keine Dialog-Elemente mehr Aktualisiert werden (ich deaktiviere einige bei start aus sicherheitsgründen). Nur bei Verschieben des Fensters aktualisieren die sich. Woran liegt das? ist aber nur nebenbei und wäre nett, wenn das einer weiß.

    Wenn ich meine Logdatei anschaue, dann habe ich ca. 123 Einträge die Sekunde drin. Passt also ganz gut. Nun wollte ich das ganze unter Vista testen. Aber hier komm ich nur auf 63 Einträge, was bedeutet, dass ich nur alle 15ms einen Report lese. Woran liegt das? UNterstützt vista "THREAD_PRIORITY_TIME_CRITICAL" nicht?

    Im Thread rufe ich eine Routine auf, die Mir die Daten ausliest, in mehrere Arrays speichert und dann zum schluss zum Zeichnen eines Diagramms Invalidate(FALSE) aufruft.

    Zur info:
    Der XP-Rechner ist ein Singlecore Intel M-Prozessor.
    Der Vista-Rechner hat einen Dualcore Intel.
    Beide Systeme laufen als 32-Bit Version.

    Danke schmal fürs lesen 😉



  • Naja, THREAD_PRIORITY_TIME_CRITICAL bremst ja sogar den Taskmanager übel aus. Das würde erklären, warum die Dialogelemente nicht aktualisiert werden. So einen Effekt hatte ich auch schon mal. Hast du auch ein Sleep(0) eingebaut? Soll teilweise helfen.
    Was Vista angeht: Hast du das Program auch mit der Option für Dual-Core compiliert?


  • Mod

    1. Kein Windows OS ist ein Ectzeit System.
    2. Vista hat evtl. noch was anderes zu tun. Zudem sorgt Vista besser dafürt, dass Threads die agressiv Prozesszeit rauben, schneller ihre Zeitscheibe verlieren.
    3. Dein eigener Mainthread kommt nicht mehr an die Reihe, weil Dein aggresiever Background Thread alle Zeit frisst.
    4. Alleine der Aufruf von Invalidate aus dem Backgroundthread ist der größte Quatsch, den Du machen kannst. Führe nie UI Operationen aus einem Backgroundthread aus. Alleine das wird Dich immens Zeit kosten.

    Frage: Wartest Du nie auf irgendein Ereignis in dem Backgroundthread?

    Grundsätzlich: Vermeide THREAD_PRIORITY_TIME_CRITICAL! Wähle andere Verfahren für den IO!



  • Ich versuch mal einen THREAD_PRIORITY_HIGHEST und eins darunter. Vllt. klappts ja da auch schon mit meinen 125 Herz.

    Wo soll ich denn das Sleep einbauen? direkt im Thread? Da ist doch schon ein Sleep(8) drin.

    Ne ich hab jedenfalls nicht konkret eingestellt, dass ich das für 2-Core CPUs compilieren will. Wo stell ich das denn ein und hat das nachteile für Singel-Core CPUs? Soll ja schließlich auf beiden laufen.



  • @ Martin:

    Das Windows alles anderes als Echtzeit ist ist mir schon klar. Leider ist die Vorgabe so nah wie möglich an die 125 Hz zu kommen. Das schafft der Timer leider nicht (15ms minimum) und am Multimedia-Timer bin ich leider gescheitert.

    Leider hab ich noch nicht so viel Viste-Kenntnisse dass ich mich da gut auskenne, was es kann und was nicht. Mir ist nur aufgefallen, dass die Speicherverwalltung besser ist (laut Task-Manager run 60% geringer als bei Windows).

    Ich muss eine Grafik anzeigen und aktualisieren. Wo soll ich denn sonst bitte die Grafik aktualisieren? Irgendwo muss ich ja Invalidate aufrufen oder nicht?

    Ich warte auf keine Ereignisse im Background-Thread.Ich les nur daten aus und die Kommen automatisch alle 8ms.

    Was für ein Verfahren würdest du denn Vorschlagen, damit ich die Zeit einhalte?



  • Dass die Daten alle 8 ms ankommen, heißt doch nicht, dass du auch die Grafik alle 8 ms aktualisieren musst. So schnell kann doch sowieso kein Mensch gucken.



  • Stimmt schon, aber meine Grafik ist ne Kuve, die Kontinuierlich durchläuft (wie die Auslastung im Taskmanager) und das auf einer Grafikbreite von 900x700 (3 X-Achsen).

    Ist zwar schnell, aber flüssig und fast zeitgleich zu den Daten. Wenn ich die Ausgabe langsamer aktualisiere, dann Ruckelt es so und das sieht nicht schön aus.

    Wie schauts eigenltich mit einem Multimedia-Timer aus. schafft der das mit den 8ms?
    Wenn ja, welchen und wie?

    EDIT:
    Hier mal ein Pic http://www.pictureupload.de/originals/pictures/030608104357_grafik_graph.JPG


  • Mod

    Uruk-h4j schrieb:

    Das Windows alles anderes als Echtzeit ist ist mir schon klar. Leider ist die Vorgabe so nah wie möglich an die 125 Hz zu kommen. Das schafft der Timer leider nicht (15ms minimum) und am Multimedia-Timer bin ich leider gescheitert.

    Warum?

    Uruk-h4j schrieb:

    Leider hab ich noch nicht so viel Viste-Kenntnisse dass ich mich da gut auskenne, was es kann und was nicht. Mir ist nur aufgefallen, dass die Speicherverwalltung besser ist (laut Task-Manager run 60% geringer als bei Windows).

    Heißt doch gar nichts! Der ist viel zu träge!

    Uruk-h4j schrieb:

    Ich muss eine Grafik anzeigen und aktualisieren. Wo soll ich denn sonst bitte die Grafik aktualisieren? Irgendwo muss ich ja Invalidate aufrufen oder nicht?

    Aber doch in keinem Fall in dem Thread der die Arbeit tut!
    Setze einen Event, der im Mainthread auf der UI Seite zum Invalidate führt!
    UI und Workerthread sollten/müssen immer streng entkoppelt werden.

    Uruk-h4j schrieb:

    Ich warte auf keine Ereignisse im Background-Thread.Ich les nur daten aus und die Kommen automatisch alle 8ms.

    Und woher weißt Du das die Daten neu sind?
    Was passiert wenn du 24ms nicht liest?
    Was passiert wenn Du schneller als 8ms bist?

    Das ist keine Antwort und behandelt nicht das Problem!

    Was für ein Verfahren würdest du denn Vorschlagen, damit ich die Zeit einhalte?[/quote]



  • Uruk-h4j schrieb:
    Das Windows alles anderes als Echtzeit ist ist mir schon klar. Leider ist die Vorgabe so nah wie möglich an die 125 Hz zu kommen. Das schafft der Timer leider nicht (15ms minimum) und am Multimedia-Timer bin ich leider gescheitert.

    Warum?

    Hab viele Posts gelesen, die mit Multimedia-Timer zu tun hatten. Hab auch ne Frage zu gestellt, aber keine schlüssige antwort zu meinem Problem bekommen. http://www.c-plusplus.net/forum/viewtopic-var-t-is-214722.html

    Und woher weißt Du das die Daten neu sind?

    Es handelt sich um einen BEschleuigungssensor am USB. Der schmeist mir die Daten um die ohren. Steht so im Datenblatt und kann man auch mit diversen Tools nachvollziehen.

    Was passiert wenn du 24ms nicht liest?
    Was passiert wenn Du schneller als 8ms bist?

    Wenn ich die Daten alle 24ms lese ist die Aufzeichnung (Datenlogging) ungenauer. Und die Vorgabe ist nunmal "Es muss alle 8ms sein". Kommt nicht von mir sondern Cheffe 😉
    Wenn ich schneller als 8ms bin, dann bekomme ich die letzten Daten die gesendeet wurden (Buffer). Ist aber nicht erwünscht, dass ich schneller bin, weil das nicht den Spezifikationen des Gerätes entspricht. Bin jetzt bei 124Hz und damit ist Cheff zufrieden, aber mich quält halt, dass der Thread unter Vista anders verhalten zeigt und halt das mit den Steuerelementen.



  • So bin fertig mit der Welt.
    Hab jetzt den Thread gegen einen Multimediatimer ersetzt (ja ich habs hinbekommen *stolz binz*). Jetzt läufts auf XP und Vista gleich und ich bin den murks-thread los.

    Das einzige problem ist jetzt, dass die Steuerelemente (z.b. Menü) nicht mehr drauf reagieren, wenn man mit der Maus drüber zeigt. Erst bei klicken gehts weiter. Scheint aber daran zu liegen, dass 8ms etwas anstrengend sind. Weiß da noch einer rat oder muss ich damit leben, wenn ich so schnell sein will?


  • Mod

    Dir Frage ist einfach, wie oft kommt die Messageloop enfach noch zum tragen. Ist denn das ganze nun in einem Thread?



  • nee..hab den thread rausgenommen und gegend einen Multimedia-Timer ersetzt.
    Läuft jetzt alles im Haupt-Thread der Anwendung. Ist mir auch lieber so. Muss man nicht so viel beachten mit Thread-Sicher und Synchronisierung.

    Danke für eure Hilfe !


  • Mod

    Dann hast Du einfach hier das Problem, weil es eben im selben Thread läuft...

    Das ist schon ein Fall für einen Workerthread ;)!



  • ich lass es jetzt so wie es ist.
    Ob nun mit Worthread oder ohne es läuft stabil und wenn sich einer dran stört soll er es für sich behalten ;). Das Problem ist ja an sich die extram kurze Zeitspanne und Windows... Ob ich das jetzt nun in einen Workthread packe oder nicht. 8ms sind 8ms. Und es läuft mit dem Multimediatimer auch unter Vista wie gewollt druch. Mehr will ich nicht und muss auch nicht sein. Man kann auch zu viel Zeit investieren und da ich dafür bezahlt werde, das Programm aber Freeware ist muss man halt abwägen ob sich der Mehraufwand kostentechnisch lohnt.



  • zum thema gui aktualisieren .. wenn du nen thread hast hast, darin daten liest, dann schicke in jedem zyklus ne SendMessage an die Gui, "aktualisiert dich" dann brauchst in dem thread das fenster handle nicht in dem er läuft...

    os macht man das doch im normalfall oder?

    ich habe ne eigen timer klasse implementiert, welche einen thread startet, und ihn über pause/Continue funktione via events anhält und weiterlaufen läst, zudem schickt der thread in angegene zyklus eine Eindowmessage an das gewünschte fenster...

    Ich nehme den thread für die kommunukation mit einem exteren gerät an der comschnittstelle...

    die 8ms in deinem thread sind flott..dier aufzeichnug der daten dauert eben brauch leistung...jed nachdem wie du es gemacht ahst


  • Mod

    BorisDieKlinge schrieb:

    zum thema gui aktualisieren .. wenn du nen thread hast hast, darin daten liest, dann schicke in jedem zyklus ne SendMessage an die Gui, "aktualisiert dich" dann brauchst in dem thread das fenster handle nicht in dem er läuft...

    Genau das ist Unsinn, wer SendMessage an einen UI Thread schickt muss sich nicht wundern, wenn der Workerthread ausgebremst wird. Gerade in diesem Fall in dem es auf Speed ankommt ist SendMessage mit 100% der falsche Weg!

    In soilch einem Fall sollte der UI Thread entkoppelt arbeiten und über einen Event oder en Flag über neue Daten benachrichtigt werden.



  • Martin schrieb:

    In soilch einem Fall sollte der UI Thread entkoppelt arbeiten und über einen Event oder en Flag über neue Daten benachrichtigt werden.

    das meinte ich ja ich lasse mein thread ein vector voller daten hollen was ne zeit gehen kann.. dann schickt der thread ein event "gelesen" welches via PostMessage an die Gui geschickt wird.. die Gui implementiert eine OnDate funktion welche auf das entsprechedne Event anspringgt und ei nzeiger auf die Daten hält.

    Das Problem ist wenn die Gui nicht nachkommt die daten zu lesen, und der thread schon wieder neue schreibt.... Dann entweder die Daten kopieren und der Gui geben, oder SendAsyncMEssage oder sowas verwenden..

    irgend ein weg muss man ja gehen umd mit Thread und UI daten auzutauschen...

    Oder: soll ich die daten global halten, so das UI und thread nen zugriff drauf haben, und über das Event sag ich der UI , jetzt sind neue daten da? natürlich noch mit nem Mutex syncronisiert?


  • Mod

    1. Brauchst Du nur ein PostMessage zu machen, wenn der UI Thread alle Daten ageholt hat. Bei Deiner Methode und den schnellen Updates wird der UI Thread ja mit Messages bombadiert, dier er kaum abarbeiten kann!
    2. Kann man ohne Probleme mit Events arbeiten!



  • naja mein comport thread hat nen zyklus (min.) von einer sekunde...
    Sorry.. ja ich meinte PostMessage

    Was ich mir aber noch überlegen musst, ist das ich bei jedem zyklus ja quasie nen neuen datensatz + zeitstempel de GUI übergebe. Den will ich nicht nur anzeigen , sonder auch noch in ne datei speichern.. soll ich das auch in dem Event übernehmen, oder ist das schlechter stil?


Log in to reply