Laden...

Ablauf/ Struktur einer Echtzeit Anwendung (hier 33ms ) Bildschirm Darstellungsproblem

Letzter Beitrag vor 8 Jahren 52 Posts 10.032 Views
Thema geschlossen
Ablauf/ Struktur einer Echtzeit Anwendung (hier 33ms ) Bildschirm Darstellungsproblem

(vorab: leider mußte ich Echtzeit schreiben, da wirklich alle 33ms eine Antwort erfolgen muß. Möchte aber keine Diskussion über Echtzeit anregen)

Hallo,

folgendes Problem.

Rahmenbedingungen:

  • Einplatinen Computer lüfterlos mit WES7 (Windows Embedded Standard 7)
  • die Anwendung ist die einzige Anwendung auf dem Rechner

Die Rahmenbedingungen sind halt leider mit ausschlaggebend, da die Anwendung auf z.B. einem Intel Core i5-3570 mit entsprechender Grafikkarte ohne Probleme läuft. Zum Testen habe ich mir einen Rechner mit einem Celeron J1900 Processor geholt, da dieser im Moment wohl der leistungsstärkste lüfterlos zu betreibende ist mit der neusten HD Graphics. Dieser kommt schon an seine Grenzen und die Anzeige hinkt ab und an und dies ist leider nicht akzeptabel.

Anwendungs Beschreibung:
Die Anwendung bekommt über Tcp/Ip von einem Windows CE6 Rechner (auch eigen programierung) alle ca. 33ms (30/sec) einen Timecode Wert, je 130 Messwerte (0-1024) und Schalterstellungen (0-1) übertragen. Diese Werte müßen einzeln (130 Kanäle) in Abhängigkeit unter anderem von der zugehörigen Schalterstellung und des Timecodes bearbeitet, zwischengespeichert und wieder zurückgegeben werden. Am Ende eines Messdurchganges, max. 60 Minuten, müßen alle Werte in einer Datei gespeichert werden.
Der Windows CE6 Rechner steuert eigen entwickelte analoge Ein- Ausgabe Karten und nimmt noch einzelne Char Werte einer Tastatur (keine Pc Tastatur) entgegen und leitet diese auch über Tcp/Ip an den WES7 Rechner weiter, der diese zu Befehlen zusammen setzt. Die Eingabe über diese Tastatur ist die einzige Steuerungs möglichkeit der Anwendung. An dem ganzen System befindet sich also keine Maus und keine Pc Tastatur.
An den WES7 Rechner sind zwei Bildschirme angeschlossen zur Anzeige der Tastatureingaben für die
Bedienung, der Zeit (frame genau) sowie der Messwerte in Form eines Balkens je Kanal (Bargraph-Anzeige).

Problem(e):
Im moment läuft die Datenübertragung über eine syncrone Socket Verbindung (WES7 TcpServer, CE6 TcpClient). Das Datenpaket wird angenommen, bearbeitet und mit den neuen Daten als Antwort zurückgesendet. Während der Bearbeitung (1) wird
(2) der übermittelte Timecode angezeigt
(3) die Bargraph-Anzeige aktualisiert
(4) die Tastatureingaben ausgewertet und angezeigt.

Da es zu jedem empfangenden Daten Paket nur exakt ein Antwort Paket gibt (können ja auch aufgezeichnete Daten sein die zurück geschickt werden), kann der gesamte Ablauf der Anwendung doch nur syncron erfolgen, oder ist da schon der erste Denkfehler?
(2)(3)u.(4) müßen natürlich nicht jeden Durchlauf angezeigt werden.

Mein Problem ist die Gui Aktualisierung (2)(3)u.(4). Die Zeitanzeige (2) sollte z.B. unter allen Umständen, unabhänig von der Auslastung der Anwendung holperfrei durchlaufen, wie z.B. bei Cubase oder anderen Programen mit Timecode Anzeige. Mit beschäftigt und ausprobiert habe ich unteranderem Windows Forms, WPF, WPF mit Windows Forms Host, RenderTargetBitmap, SharpDX/SlimDX mit/ohne WPF Host, usw. .
Wenn ich die Gui abschalte benötigt ein Durchlauf der Daten (1) ca 1- max. 5ms incl. Empfangen/ Senden und die ganze Bearbeitung ist noch lange nicht optimiert.

Da ich mich mit der Anwendung nun schon sehr lange beschäfige, befürchte ich ein wenig blind für das eigentliche Problem zu sein und hoffe hier die erlösende Hilfe zu bekommen.
Ich habe versucht den Zusammenhang so umfangreich wie erstmal nötig darzustellen, aber beantworte gerne spezielle Rückfragen. Alles aufzulisten was ich schon versucht habe erschien mir nicht hilfreich.

Bin für jede Hilfe sehr dankbar.

Da es zu jedem empfangenden Daten Paket nur exakt ein Antwort Paket gibt (können ja auch aufgezeichnete Daten sein die zurück geschickt werden), kann der gesamte Ablauf der Anwendung doch nur syncron erfolgen, oder ist da schon der erste Denkfehler?

Ja, da ist ein Denkfehler.

Erstelle einen Daten Thread und einen Darstellungsthread.

Nach erhalt des Datenpackets erstellst du die Antwort und sendest diese.
Wenn du das in 1-5ms hinbekommst ist da schon mal alles OK.

Sende intern das auszuwertende Packet in eine Queue ( herbivore hat hier eine nette SyncQueue <T> - Eine praktische Job-Queue oder z.b. Memory Queue ).

Dein Darstellungs thread ist so getrennt .

Hallo luciluke,

ergänzend zu FZelles Antwort schau dir auch Pipelines an.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

Hallo FZelle,
mit "syncron erfolgen" meinte ich auch nur die Daten empfangen, bearbeiten und wieder senden. Nicht die Darstellung. Vielleicht einwenig unglücklich formuliert in meinem Anfangs post.
In meinem "TcpServer" läuft ein Thread der den anfragenden Client verbindet und dann wenn ein Paket empfangen wurde wird dieses bearbeitet und wieder zurückgeschickt.
Das wäre ja dann mein Daten Thread, oder?

Für die Anzeigen mache ich immer nach Erhalt eines Paketes eine Kopie der Daten, der Daten Thread läuft weiter.
Diese Kopie habe ich schon einmal einer BlockingCollection<T> hinzugefügt und für die Anzeige in einem extra Task der vom Hauptthread erstellt wurde consumiert, um dann bei z.B. WPF mit hilfe von MVVM usw. z.B. die Zeit anzuzeigen.
Das wäre ja vergleichbar mit SyncQueue ... .
Wobei sich für mich da die Frage stellt was da der Darstellungs Thread ist. Der Task der consumiert und das Property ändert oder das ganze interne WPF Binding danach.

Ich habe auch schon mit einem Timer gearbeitet der die Kopie alle 80ms oder so dargestellt hat. Aber eine 100% flüßige Anzeige des Timecodes unabhängig von der restlichen Programauslastung bekomme ich da einfach nicht hin.

Nach erhalt des Datenpackets erstellst du die Antwort und sendest diese.
Wenn du das in 1-5ms hinbekommst ist da schon mal alles OK.

Das bekomme ich incl. der Datenkopie hin.

Hallo gfoidl,
danke für den Hinweis. Hatte ich mich auch schon mit beschäftigt, aber das war soweit ich mich erinnere wohl eher etwas um die Bearbeitung meiner Daten noch zu beschleunigen, aber da die Zeit für die Bearbeitung nicht das Problem war und ist hatte ich das auch nicht weiter verfolgt. Wenn ich das mit der Anzeige in den Griff bekomme, ist das natürlich zu überlegen.

Hallo luciluke,

nicht nur um die Bearbeitung zu entschleunigen, sondern Teile zu entkoppeln und nebenläufig laufen zu lassen. Genau das was du willst.

Es wird nun in den meisten Beispielen für eine Beschleunigung dargestellt, aber Pipelines bzw. Producer/Consumer sind viel allgemeiner einsetzbar.
Der eine produziert und stellt es in einen Buffer.
Der andere verarbeitet und liest aus dem Buffer.
Ist der Buffer voll, kann der andere nix schreiben und ist er leer, kann der eine nix lesen und muss warten. So einfach ist im Prinzip. Das lässt sich auf viele Aufgaben ummünzen.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

Hallo,
ist zwar schon was länger her, aber da ich das Problem nur aufgeschoben habe, muß ich doch nochmal einen Versuch starten und um Hilfe/Ideen bitten.
Kurzfassung/Eingrenzung:
Also es geht eigendlich nur darum einen Text mit 9 Zeichen möglichst exact alle ca. 33ms anzuzeigen mit einem Celeron J1900 Processor mit integrieter HD Graphics (Bay Trail) unabhängig von der sonstigen Auslastung des Programes.
Die Datenbearbeitung stellt zeitlich wirklich nicht (mehr) das Problem dar und ist getrennt von der Darstellung.
Aber wann in WPF mit Databinding gezeichnet wird ist vielleicht noch nicht so optimal.

Biete unendliche Dankbarkeit für den entscheidenden Hinweis.

Gruß luciluke

Wo genau hängst Du noch?

Aber davon abgesehen: exakt 33ms wirst Du das nicht robust hin bekommen, da Windows - auch Embedded - kein _wirkliches _Echtzeitsystem ist.
Jede Windows Variante hat gewisse Delays (zB. WinCE ca. 50-200 µs), die eine 100% exakte Ausführung nicht möglich machen.
Wenn die Applikation aber gewisse Delays toleriert kann man das wiederum als Hard- oder Soft Real-Time sehen.

zB. wenn Du Thread.Sleep(1) ausführst, was prinzipiell 1ms bedeuten würde, wirst Du sehen, dass das 15-30ms benötigt.
Unter .NET hängt eine Virtual Machine (IL+JIT+CLR) und das alles ist gewiss nicht Echtzeit.

Hallo Abt,
im Prinzip brauche ich wohl eine Technik mit der ich Bereiche des Bildschirms mit unterschiedlicher Priorität zeichenen kann. Zum einen gibt es diese Zeitanzeige, die halt an der letzten Stelle alle 33ms (30fps) aktuallisiert und einen zweitrangigen Bereich in dem ca. 60 Balkenanzeigen (Pegelanzeigen) gezeigt werden.
Und diese Zeitanzeige soll halt immer gleichmässig laufen, es würden natürlich auch z.B. alle 60ms gehen, aber halt gleichmäßig. Das fängt dann immer an ein wenig zäh zu laufen, kann ich nicht anders beschreiben. Kein Echtzeitsystem ist klar, aber z.B. Cubase oder Digijay bekommen ja auch eine Zeitanzeige hin, wo die hintere Zahl gleichmäßig durchläuft bzw. wo es wenigstens so aus sieht.

Irgendwie hört sich das so an als ob Du gar nicht weißt, warum es bei Dir zeitlich nicht hin haut.
Wieso überwachst Du nicht einfach mal mit ner simplen Stopwatch wie lange Du für das Zeichnen via WPF benötigst? In der MSDN gibts dazu auch ein Beispiel, wie man die FPS sehr einfach anzeigt.

Trotzdem wirst Du Dich mit der Kombination Windows+.NET sehr schwer tun eine exakte, robuste, dauerhafte Wiederholung von 33 oder 60ms hin zu bekommen.
Das wird am Ende sehr wahrscheinlich immer auf ein gewisses Range hinaus laufen.

Wenn es einfach nur gleichmäßig laufen soll:
Wieso cachst Du die pushten Daten nicht einfach und "überträgst" diese Daten dann nicht einfach alle X Millisekunden (zB. via Timer) in das WPF-ViewModel?

... wenn ich das wüßte, wäre es ja auch zu einfach.

Ja, es soll einfach nur gleichmäßig laufen und ich mache das auch im Moment schon mit zwei Timern alle 90ms die Zeitanzeige und alle 150ms die Pegelanzeige.
Aber auch das schwankt. Die FPS wird mit 40-50 angezeigt.

Ich kann mich gern wiederholen:

Trotzdem wirst Du Dich mit der Kombination Windows+.NET sehr schwer tun eine exakte, robuste, dauerhafte Wiederholung von 33 oder 60ms hin zu bekommen.

Ich hätte den Range auch höher als 10FPS eingeschätzt.
Robust, dauerhaft identische 60 FPS wirste Dir was anderes als WPF suchen müssen.

WPF ist für diesen Fall bzw. Anforderung gar nicht gedacht.
.NET übrigens auch nicht wirklich.

Ich werd auch nicht schlau draus, warum es in diesem Fall die Anforderung von Dauerhaft X FPS gibt, wenn sie höher ist als ~27 FPS.
Kann sowieso kein Mensch unterscheiden geschweige denn was mit den Mehrinformationen anfangen.

.NET ist für deine Anforderungen die falsche Technik.
Du solltest hier eher mit Nativen Sprachen wie C/C++ arbeiten.
Diese sind eher für Echtzeitanforderungen gedacht.
Google sollte dir hier weiterhelfen können :p

Nachtrag:
Ist WES7 eigentlich Echtzeit getrimmt?
Oder handelt es sich dabei nur um eine Embedded Version von Windows?
Falls dies nicht für Echtzeit Optimiert ist, wäre vielleicht ein RTS Linux besser geeignet?
Da du ja ein festes Zeitfenster hat, entspricht dies ja tatsächlicher Echtzeit 😃
Hier müsstest du dann eben auch mit C/C++ ein Tool bauen.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

@Abt:

Ich werd auch nicht schlau draus, warum es in diesem Fall die Anforderung von Dauerhaft X FPS gibt, wenn sie höher ist als ~27 FPS.
Kann sowieso kein Mensch unterscheiden geschweige denn was mit den Mehrinformationen anfangen.

Ist mir vollstens bewust, deshalb schrieb ich ja auch "... bzw. wo es wenigstens so aus sieht".

@T-Virus:
die Datenakquisition mache ich ja wie geschrieben schon in c/c++ mit einem CE6 Modul

Ich hoffe aber immernoch, da auf einem leistungsstärkeren Rechner mit Grafikkarte die Gleichmäßigkeit gegeben ist. Trotz .net, wpf, ca.15ms timer Auflösung und und und ...

Hi,

was mir jetzt beim durchlesen aufgefallen ist. Ist das du mehrmals einen Timer zum aktualisieren erwähnst. Eigentlich sollte es funktionieren nach dem Empfang der Daten die UI über ein Event zu aktualisieren.

Die physikalischen Grenzen hat ja Abt schon erwähnt. Ich denke an dem Punkt wäre es vielleicht sinnvoll. Wenn du mal genau erklärst wie du es Implementiert hast (Quellcode wäre hilfreich).

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

Hallo, erstmal danke für die Antworten,
habe das ganze jetzt auch nochmal ganz schlicht ohne async, ohne Queue usw. gemacht.
Daten kommen über Netzwerk rein, Zeit wird angezeigt, Daten werden bearbeitet, Daten werden zurückgeschickt.
Wobei bei der Zeitanzeige durch Dispatcher.BeginInvoke(new Action(NewMethod), DispatcherPriority.Send); oder ähnlichem ja schon doch noch etwas asyncron ausgeführt wird um in den UI Thread zu kommen.
Aber auch hier sieht man halt ungleichmäßigkeiten in der Zeitanzeige abhängig von der Systemauslastung.

@Palin (Quellcode wäre hilfreich)
Ich wüßte nicht wo ich da anfangen sollte.
... Wie schon oben geschrieben: Wenn ich die Gui abschalte benötigt ein Durchlauf der Daten (1) ca 1- max. 5ms incl. Empfangen/ Senden ...
Ich hätte also noch gut 20ms Zeit für die Anzeige und das reicht halt nicht immer.

Ich werde wohl einen etwas leistungsstärkeren Prozessor testen müßen und mich dann leider von der lüfterlosen Variante verabschieden, das war ja eigentlich mein Ziel.

Aber die Hoffnung stirbt zu letzt, Ideen werden noch gerne getestet.

Wobei bei der Zeitanzeige durch Dispatcher.BeginInvoke(new Action(NewMethod), DispatcherPriority.Send); oder ähnlichem ja schon doch noch etwas asyncron ausgeführt wird um in den UI Thread zu kommen.

Ich würde sowas komplett von der GUI entkoppeln. Vielleicht Daten in eine Queue schreiben und in der GUI einen Timer laufen lassen, der ab und zu nachschaut, ob neue Daten in der Queue sind und die Anzeige aktualisiert.
Auf die Weise müsstest du das schon "gleichmäßig" hinbekommen können, auch ohne einen leistungsfähigeren Prozessor. Ich muss bei sowas an Musiksoftware denken, und solche Spielereien wie die Musik durch irgendwelche grafischen Effekte zu visualisieren liefen bei mir schon auf einem 400 MzH Rechner völlig flüssig.

Das hab ich auch schon vorgeschlagen; aber scheint irgendwie nicht gewünscht zu sein...

Hallo Abt Hallo Coder007,
ich hatte es jetzt ja nur nochmal ohne Entkopplung getestet, da Palin meinte es mal ohne Timer zu versuchen und das dies nicht zu Erfolg geführt hat habe ich geschrieben.

@Coder007:

...solche Spielereien wie die Musik durch irgendwelche grafischen Effekte zu visualisieren

Wenn Du die grafischen Effekte mal mit einer Frameanzeige, also einer hochlaufenden Zahl ersetzt, würdest Du warscheinlich auch Unregelmäßigkeiten sehen. Bei z.B. einer Balkenanzeige meine ich auch alles flüßig zu sehen, aber anscheindend kann man Zahlen genauer wahrnehmen, da man daran gewöhnt ist zu zählen oder so, nur eine Vermutung. Und wenn ich mir z.B. die Visuallisierung vom VLC Player ansehe (VU Meter), dann sieht man, daß diese unter anderem erst ca. 500 ms später anläuft und auch genauso lange nachläuft, wenn gestoppt wird, da wird anscheinend gar nicht auf das Timing geachtet hauptsache es bewegt sich was. Das reicht bei meiner Anwendung leider nicht so ganz.

Ich versuche jetzt nochmal die Variante mit zwei Timern und zwei ConcurrentStack für jeweils Zeit- und Pegel-Anzeige, da ich ja eigentlich auch davon überzeugt bin, daß dies die beste Lösung ist.

Vermutlich wirds hier weniger eine Rolle spielen; aber manuelles Locking ist performanter als die Concurrent-Klasse.

Hallo,
kommt denn tatsächlich alle 33 ms ein Paket an oder werden auch mal in einem TCP-Paket mehrere Wertfolgen übertragen? Auch das könnte das Flackern erklären, da ja dann ab und an mal ein Paket mit den 130 Werten wartet und mal 2x oder 3x so viele in einem Paket sind.

Hallo Abt Hallo Coder007,
ich hatte es jetzt ja nur nochmal ohne Entkopplung getestet, da Palin meinte es mal ohne Timer zu versuchen und das dies nicht zu Erfolg geführt hat habe ich geschrieben.

Nun das hab ich ein bisschen anders gemeint. Mir ist nicht klar wie so du überhaupt einen Timer zum aktualisieren verwendest.

Grundlegend hast du ja einen Thread der die Daten aktualisiert. Nach dem aktualisieren sollten, die Daten einfach ein Event schmeißen (z.B. Property Change) auf Grund dessen du die Oberfläche aktualisierst.

Grundlegend sollte die Oberfläche schnell genug sein die Daten ruckelfrei darzustellen. Es gibt Leute die haben einfache "Echtzeitspiele" (z.B. Blockout) mit Windows Forms umgesetzte. Die ohne zu ruckeln auch auf alten Rechnern laufen.

Meine Vermutung an dem Punkt ist, das du da was machst was nicht so Optimal ist. Was es genau ist müsste man jetzt Raten und da gibt es einfach X-Möglichkeiten.

Und meines erachten ist es da schwer ohne Implementierungsdetails eine Aussage zu zutreffen. Du musst entweder genauer beschreiben, was du wie machst oder uns den nötigen Quellcode zeigen. Wenn der eigentliche Quellcode zu umfangreich ist, kannst du vielleicht ein einfaches Beispiel Projekt erstellen an dem man das Problem sehen kann. (Für die Klasse, die die Daten Liefert kannst du ja einen Dummy erstellen, der in einen eigenen Thread läuft x ms schläft und dann die Daten endert)

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

Mit einem Timer nimmst Du schon die Last ab.
Es gibt keine Notwendigkeit bei einem Diagramm 100 FPS erreichen zu wollen - völlig verbratene Leistung.

@Abt Da hast du schon recht, ich kann mit einem Timer die Anzeige verzögern. Aber wenn ich es richtig verstanden habe ist sein Problem doch, dass die Anzeige nicht oft genug Aktualisiert.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

@Palin Das Problem ist, daß es nicht gleichmäßig genug aktuallisiert, nicht nicht oft genug aktualisiert.

@pinki alle 33 ms +- 3ms ein Paket

Palin, luciluke versteht leider oder will vermutlich nicht verstehen, dass er keine 100%tige Gleichmäßigkeit hier erreichen kann.
Die höchste Gleichmäßigkeit, die er erreichen kann (denke ich), ist alle ~50-100ms die Anzeige aus einem Datenpool durch einen Timer zu aktualisieren.
luciluke hat leider bis jetzt überhaupt nicht verstanden, oder ignoriert es, dass exakt alle 33ms etwas zu verarbeiten und dann auch noch zu zeichnen in dieser Umgebung nicht möglich ist.
Die Gründe wurden nun Mehrfach von mehreren Personen genannt.

Eine Anzeige, die das Auge gar nicht verarbeiten kann, macht bei dieser Art von Content überhaupt keinen Sinn und definitiv einen Fall von Over-Engineering bzw. "wir wollens halt!".

Wir reiten hier einen toten Gaul.

@Abt ich stimme dir da fast 100% zu. Besonders der Aussage : "
Eine Anzeige, die das Auge gar nicht verarbeiten kann, macht bei dieser Art von Content überhaupt keinen Sinn und definitiv einen Fall von Over-Engineering bzw. "wir wollens halt!"."

Für mich stellt sich an den Punkt, die Frage wo genau sein Problem ist.

Genau 33ms geht natürlich nicht. Aber nach erhalten des Messwertes sollte die GUI in der Lage sein ihn schnell genug Anzuzeigen (Grob 60Hrz ungefähre 17ms). Sollte das Auge nicht mitbekommen.

Ich persönlich hab, das Gefühl, dass wir luciluke´s Problem nicht wirklich verstehen (Mag an ihm liegen). Deshalb würde ich ganz gerne Quellcode sehen. Vielleicht kann man da dann doch noch was machen.

Ansonsten würde ich es wie die Indianer halten:
"Wenn Du entdeckst, dass Du ein totes Pferd reitest, steig ab."

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

Hallo Abt, Hallo Palin
ich kann das jetzt nicht so stehen lassen, das ich das nicht verstanden hätte.

In meinem letzten Post habe ich lediglich die Frage von pinki beantwortet und die Pakete kommen nunmal alle 33ms +-3ms rein. Und ich habe die Problemstellung von "nicht häufig genug" auf "nicht gleichmäßig genug " richtiggestellt, da Palin danach fragte.
In meinem vorletztem Post habe ich doch auch geschrieben:

Ich versuche jetzt nochmal die Variante mit zwei Timern und zwei ConcurrentStack für jeweils Zeit- und Pegel-Anzeige, da ich ja eigentlich auch davon überzeugt bin, daß dies die beste Lösung ist.

und da bin ich dabei, ist halt etwas umfangreicher.
Und wenn ich da ein einigermaßen befriedigendes Ergebniss hinbekomme, versuche ich mal in Auszügen den gesamten Weg zu posten, um schauen zu können, wo es noch besser geht. Allein für die Anzeige der Zeit in WPF gibt es ja schon einige unterschiedlich Wege.

Der tote Gaul ist also fleissig und bestimmt nicht beratungsresistent.
Im Gegenteil ich freue mich ja, das Ihr mir helft. Und das habt Ihr jetzt schon!

Bei z.B. einer Balkenanzeige meine ich auch alles flüßig zu sehen, aber anscheindend kann man Zahlen genauer wahrnehmen, da man daran gewöhnt ist zu zählen oder so, nur eine Vermutung.

Kann ich jetzt nicht wirklich kommentieren. Denkbar, aber ich glaubs nicht wirklich. So viele Frames/s kann das menschliche Auge nicht auflösen. Die Standardauflösung von Windows Timern ist 15ms, das dürfte völlig ausreichend sein.
Das kannst du ganz einfach ausprobieren, indem du einen Timer schreibst, der alle 33ms ein Label aktualisiert, völlig unabhängig von irgendwelchen Paketen.

Nimms mir nicht übel Luciluke, aber wenn ich Dein Chef wäre würde ich Dir die Hammelbeine lang ziehen.
Wie viel Stunden und Geld Du mit einer völlig unnötigen Sache verbrätst - finde ich - enorm verantwortungslos.
Ein Entwickler sollte nicht nur fachlich, sondern auch verantwortungsvoll handeln.

Das Auge kann informativ nicht mehr als 3-4 verschiedene Werte pro Sekunde kurzfristig verwerten.
Erkennen kann es mehr, aber nicht sachlich verarbeiten.

Was Du machst ist die absolute Verschwendung von Ressourcen.
Ihr scheint echt wenig Probleme zu haben, wenn ihr euch mit sowas über Tage, Wochen aufhaltet und den Kern nicht begreift oder begreifen wollt.
Ich bleib auch bei meiner Aussage, dass Du diesen Kern bis jetzt nicht verstanden hast.

Aufgrund des Fazits zieh ich mich auch aus dem Thread hier zurück.

Hallo Abt,
ist mir jetzt nicht so ganz klar, warum Du verärgert bist, bzw. Du mir jetzt hier unterstellst Sachverhalte nicht zu verstehen, zu denen ich mich gar nicht geäußert habe.

Das Auge kann informativ nicht mehr als 3-4 verschiedene Werte pro Sekunde kurzfristig verwerten. Erkennen kann es mehr, aber nicht sachlich verarbeiten.

Wo bitte habe ich irgendwo etwas gegenteiliges behauptet. Ich rede immer von erkennbar fehlender Gleichmäßigkeit.

Wenn Du mit zwei Timern zwei Label aktuallisieren läßt und ein Timer läuft mit 60ms und einer mit 90ms, beide greifen auf die gleiche Zahl zu, die mit einem Timer alle 30ms von 1 bis 30 hochgezählt wird, dann siehst Du da einen Unterschied. Und wenn Du nun eine Anzeige hast und diese zwischen diesen beiden Geschwindigkeiten springt bzw. schwankt, dann sieht das extrem schlecht aus und ist bei dieser speziellen Anwendung nicht akzeptabel. Und wenn es mit einem leistungsfähigerem Prozessor geht, dann liegt es halt eben nicht nur an Windows oder .Net, sondern kann auch am Code liegen. Und ob ein Gerät, lüfterlos gebaut werden kann oder nicht ist auch schon ein signifikanter Unterschied. Und wenn sich heraustellen sollte, dass es nicht geht bzw. ich es nicht hinkriege, dann muß halt ein leistungsfähigerer Prozessor her.

Aber Du hast selber geschrieben:

Die höchste Gleichmäßigkeit, die er erreichen kann (denke ich), ist alle ~50-100ms die Anzeige aus einem Datenpool durch einen Timer zu aktualisieren.

Ja, das wäre doch perfekt, da würde ich halt gerne landen und deshalb habe ich hier um Hilfe gebeten.
Ich habe nur in der Problemstellung die 33ms erwähnt, sonst rede ich immer nur von Gleichmäßigkeit.

luciluke hat leider bis jetzt überhaupt nicht verstanden, oder ignoriert es, dass exakt alle 33ms etwas zu verarbeiten und dann auch noch zu zeichnen in dieser Umgebung nicht möglich ist.

wo bitte habe ich zu dieser Schlußfolgerung Anlass gegeben.

Meine Aussage.

Ja, es soll einfach nur gleichmäßig laufen und ich mache das auch im Moment schon mit zwei Timern alle 90ms die Zeitanzeige und alle 150ms die Pegelanzeige.
Aber auch das schwankt.

Was ich nicht verstehe ist das Fazit, aber nun genug zu meiner Ehrenrettung.

Hallo luciluke,

du könntest dir folgende Dinge anschauen:

Multimedia Timer Dieser bietet eine bessere Auflösung als die im Framework vorhandenen Timer (~1ms).

Zusätzlich kann der GC selbst die Anwendung anhalten, was zu Rucklern führt. Ganz besonders bei full blocking collections. Möglichweise das was du als Ungleichmäßig beschreibst. Dort kann dir möglichweise die Verwendung von SustainedLowLatency weiterhelfen.

Du kannst auch die Auflösung des Windows Schedulers selbst erhöhen, so dass dieser nicht bei ~15ms liegst sondern bei 0.5ms. NtSetTimerResolution
NtQueryTimerResolution
NtSetTimerResolution

Grüße
spooky

Wo bitte habe ich irgendwo etwas gegenteiliges behauptet.

Dann stell den Timer mal auf 250 ms, das sollte doch gleichmäßig genug ausschauen.

Und wenn es mit einem leistungsfähigerem Prozessor geht, dann liegt es halt eben nicht nur an Windows oder .Net, sondern kann auch am Code liegen.

Ja, es kann auf jeden Fall auch am Code liegen bzw. man kann fast immer etwas machen. Aber dieser Satz bekräftigt doch den Eindruck, dass du das nicht einsehen willst 😉 Du hast den Scheduler von Windows nicht im Griff. Es kann immer passieren, dass er deinen Thread aus irgendeinem Grund mal 10 oder 100 ms lang nicht aufruft, und dann hast du wieder deine Ungleichmäßigkeit. Genauso kann der GC von .NET die Ausführung immer wieder mal kurz anhalten. Das hat alles nichts mit der Leistungsfähigkeit des Prozessors zu tun, das sind einfach Faktoren, die du nicht in den Griff bekommst.
Aber ich könnte mir vorstellen, dass du durch Herabsetzung der Frequenz die Auswirkungen minimieren kannst. Bei 250ms fallen 10ms Schwankungen viel weniger auf, als bei 30ms.

Google mal nach C#, Game Loop, FPS und vielleicht noch Windows Forms. Da kannst du einiges finden (Ich hab mir das jetzt nicht alles durchgelesen). Wenn du eine "gleichmäßige" Aktualisierung willst, solltest du da was finden können.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

Hallo,
da unter anderem Palin, erfreulicher Weise, noch nicht ganz aufgegeben hat, habe ich jetzt das Projekt mal auf das nötigste zusammen geschrumpft und die eingehenden Daten über einen Timer simmuliert. Die Refreshzeiten für den "Zeit anzeigen Timer (60ms)" und den "Bargraph anzeigen Timer (90ms)" können einfach ein/umgestellt werden. So wie das Program jetzt eingestellt ist läuft es auf meinem Entwicklungsrechner gleichmäßig, egal ob die Pegel unter Last angezeigt werden oder nicht, auf dem Rechner mit dem J1900 Processor jedoch nicht, oder nicht ausreichend. Es wird also ganz gut das Orginal simmuliert.
Ist jetzt nicht sonderlich kommentiert und sortiert, da ich annehme, daß man sowieso kein ganzes Projekt anhängen kann/soll, aber wie soll ich sonst die Zusammenhänge erklären. Sehr viele Codeausschnitte sind wohl auch nicht übersichtlicher, oder? (<- ernstgemeinte Frage, dann mache ich das)

ps.:
Um das doch nochmal kurz klar zustellen. Ich weiß genau, daß sowohl Windows 7 als auch WES7 keine Echtzeit Systeme sind, und ich verstehe nicht wieso mir hier teilweise das Gegenteil unterstellt wird.
Aber wenn das Program auf dem einem Windows 7 Rechner gleichmäßig genug läuft und auf dem anderen nicht, dann darf ich ja wohl behaupten, daß es nicht "nur" !!! an Windows liegt.
Das es auch an Windows und .net mit GC usw. liegt ist schon klar. Trotzdem würde ich halt gerne das beste rausholen. Es kann ja gut sein, daß ich irgendwo einen krassen Fehler mache.

Zitat aus Anfangsbeitrag:

Mit beschäftigt und ausprobiert habe ich unter anderem Windows Forms, WPF, WPF mit Windows Forms Host, RenderTargetBitmap, SharpDX/SlimDX mit/ohne WPF Host, usw. .

WPF Drawing Performance
bestätigt auch meine Tests, auf sehr unterschiedlicher Hardware (s.a.: RenderCapability.Tier, RenderOptions.ProcessRenderMode usw.) Weswegen ich auch unter anderem Windows Forms verworfen habe, da XP (XPe) keine Option mehr ist.

Gameloop scheidet wohl aus, da die Datenverarbeitung (Antwort erstellen/zurückschicken) höchste Priorität hatt. Hatte ich mich im Rahmen von DirectX usw. auch mit beschäftigt.

Naja, Du sagst zwar, dass Du weißt, dass Windows kein Echtzeitsystem ist; Du triffst jedoch Aussagen und hast Ansichten, die diesem absolut nicht entsprechen bzw. ganz weit weg davon ist.
Vielleicht fehlt es hier dann einfach am technischen Verständnis (=>100% identische Frameraten), was Echtzeit ist. Oder es ist Deine Ausdrucksweise, die eben diese Differenzen auslösen.

Habs mal gestartet. Worauf genau muss man da überhaupt achten? Kannst du das genauer erklären?

@luciluke
Aus meiner Sicht nutzt du total den falschen Ansatz und verweigerst dich den Tatsachen.
Wenn du ein sauberen Ablaufen haben willst, bist du mit deinem aktuellen Ansatz(Windows, .NET) komplett falsch.

Du kannst mit dieser Konstellation keine sicheren Aussagen zu deinem Programmverhalten machen.
Da der GC und auch der Thread Scheduler unter Windows eigene Blockzeiten haben, kannst du nie davon ausgehen, dass dein Programm immer das gleiche Verhalten aufweist.

Wenn es bei dir zeitlich auf der Entwicklermaschine passt, sagt dies nur aus das es bei dir mehr oder weniger passend läuft.
Hier musst du aber auch Szenarien prüfen wie sie auch vorkommen können, wenn Last durch CPU/Festplatte oder durch hohe Auslast des RAM erfolgt.
Ansonsten testet du einen Idealfall, der nur bei dir funktionieren wird.

Wenn du wirklich auf genaue Zeiten angewiesen bist, was du ja mit deinem bisherigen Vorgehen scheinbar brauchst, solltest du auf Linux mit Echteitkernel setzen.
Als Programmiersprache solltest du dann auf C/C++ sezten anstelle von C#
Erst dann kannst du zeitliche Abläufe auch bestimmen.

Mit Windows und .NET gibt es einfach zu viele Konstellationen bei deinen deine Vorhersagen über die Zeiten nicht stimmen können.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

@Coder007
danke, dass Du dir das mal anschaust.
Oben rechts läuft ja die Zeitanzeige, um die geht es. Wenn man in der Methode "SomeWork()" den count entsprechend einstellst, dass eine gefühlte Verlangsamung, bzw. ein anderes Muster an der letzten Stelle dieser Zeitanzeige zu erkennen ist, wenn man zwischen Pegel on/off umschaltet, dann hat man das was ich meine. Die Zeiten für die Zeit und die Pegel Anzeige können auch größer gewählt werden, aber ich denke bei der Zeitanzeige sollte es nicht mehr als 90 und bei der Pegelanzeige nicht mehr als 120 sein ( ich schreibe besser mal nicht ms ). Habe es hier jetzt nur mal relativ kurz eingestellt, um überhaupt einen Unterschied erkennen zu können, da ich nicht glaube, dass hier jemand vor ein Rechner mit Celereon oder Atom Prozessor sitzt.
Gut zu sehen ist auch, dass links oben bei der FPS Anzeige (nur für Testzwecke) der Count ziemlich unbeirrt durchläuft. Das die Zahl an den letzten zwei Stellen keinen informativen Wert haben ist klar, aber trotzdem erkennt man wohl am Muster eine vermeintliche Gleichmäßigkeit. Und um diese geht es.
Aber eigentlich geht es auch nur darum, ob diese beiden Anzeigen im Code so richtig implementiert sind. Wenn mir jemand dazu etwas sagen könnte, wäre mir sehr geholfen. Ist z.B. das erste mal, dass ich etwas mit WPF und MVVW gemacht habe.

Ich komm damit trotzdem nicht so wirklich klar... Warum werden zwei Fenster geöffnet, ist das Absicht, ist das relevant?
Warum läuft die die Zeitanzeige nur bis 30 und nicht bis 60? Das irritiert mich voll.
In SomeWork() hab ich den count mal um eine Größenordnung erhöht und einmal um eine Größenordnung verringert, und ich merk keinen Unterschied.
Ob die Anzeige jetzt gleichmäßig läuft oder nicht, kann ich subjektiv ehrlich gesagt gar nicht abschätzen. Mich stört diese Anzeige eher, die wirkt zu unruhig.

Die zwei Fenster sind Absicht, das sind dann zwei Monitore im Vollbildmodus und auf einem kann dann noch manchmal was anderes angezeigt werden, aber das fehlt jetzt hier. Wie im Eingangsbeitrag beschrieben läuft auch sonst nichts anderes auf dem Rechner, es gibt auch keine Maus und kein Keyboard. Relevant ist das, da es vom rendern her doppelte Belastung bedeutet.
Das ist eine Time Code Anzeige und die läuft bei SMPTE30 mit 30 (Film Bildern) Frames pro Sekunde, daher die 30.
Also ich habe einen Intel Core i5-3570 (wohl eher mittel schnell und auch nicht die neuste Grafikkarte) und wenn ich bei WorkOn die Pegelanzeige ein bzw. aus schalte, dann sehe ich eine schleppendere Anzeige. Bei einem Atom mit integrierter Grafik stolpert dann alles.

Ok, ich kann das soweit nachvollziehen. Dann würde ich schon sagen, dass du eindeutig etwas "falsch" machst. Die Reaktionszeit der GUI bricht komplett ein, wenn ich den count hochstelle, das sollte nicht passieren. Mir ist der ganze Aufbau aber nicht klar, von dem her kann ich nichts dazu sagen, was da falsch läuft.

Ich versuchs mal...
In TcpServer der _testTimer stellt die Simulation der eingehenden Packete dar, d.h. die Methode Receive ist noch fake.
_model.TcpServer_DataReceived(buffer); ist dann die erste richtige Methode, danach wird dieser buffer wieder als Antwort zurückgeschickt(fehlt jetzt hier).
In TcpServer_DataReceived(byte[] buffer) werden die Daten verarbeitet.
ProzessKbData(kbData_2);//=====> simmuliert hier zusammen mit dem kleinen Tasten Fenster die Keyboardbefehle die eigentlich in den empfangenen Daten enthalten sind.
In _at.ProzessData(atData) findet die eigentliche Arbeit statt.
_model.TimeCodeBufferString.Push(_model.RefreshTimeCodeString(RefInOutFrameCopyTcOnly)); stellt den Timecode String in den ConcurrentStack<string[]> TimeCodeBufferString.
In ProzessSmpteFrameAsync(incommingSMPTE); werden die Daten bearbeitet und nach der Bearbeitung wird in Push_FaderData() eine List<BargraphData> erstellt, die im Prinzip einfach nur die 129 Bargraph Werte enthält. BargraphData implementiert INotifyPropertyChanged.
Diese Liste wird in einen zweiten ConcurrentStack<List<BargraphData>> BargraphBuffer gestellt.
Das war es mit der Bearbeitung und die bearbeiteten Daten werden zurückgeschickt.
Jetzt gibt es noch einen Timer _ltcGuiTimer der alle x ms den letzten wert aus dem ConcurrentStack<string[]> TimeCodeBufferString holt, die weiteren Werte, falls vorhanden, verwirft und dann in RefreshTimeCodeWPF(string[]) in einem Objekt StatusBoxData : DependencyObject ein DependencyProperty ändert. An dieses DependencyProperty ist in MainWindow.xaml entsprechend ein Textblock gebunden.
Und es gibt einen Timer _faderGuiTimer der alle x ms den letzten Wert aus dem ConcurrentStack<List<BargraphData>> BargraphBuffer holt, die weiteren Werte falls vorhanden verwirft und dann in RefreshBargraphGui(List<BargraphData> faderData) eine zweite List<BargraphData> DicCurBargraphData aktuallisiert. An die BargraphData Objekte in dieser Liste sind "BargraphUserControls " in BargraphViewModel.cs gebunden. Und diese Liste von BargraphUserControls dienen als ItemsSource für eine angepasste ListBox zur Anzeige der Pegel. Leider benutze ich mal die Bezeichnung Bargraph mal Fader.
Wenn nötig beschreibe ich das auch gerne nochmal genauer.

Wenn man count hoch genug aufdreht, ist die CPU zu 100% ausgelastet. Ist klar, dass dein Timer dann nicht mehr so oft aufgerufen wird, wie im Leerlauf.
Allerdings stockt die GUI dann bei dir komplett und wird langsamer. Eigentlich sollte die Zeitanzeige bei dir doch die aktuelle Zeit anzeigen? Selbst wen dabei paar Events verschluckt werden, sollte die angezeigte oder verstrichene Zeit immer richtig sein. Ist aber nicht so. Dann dauert eben mal 10 Sekunden, bis der Sekundenzähler erhöht wird.
Kannst du das mal kontrollieren?

Hallo Coder007,
das ist ein Problem der Simulation, da das Zeit-Daten Packet ( hier SmpteFrame ) in dem TestTimer Tick Event erzeugt/ hochgezählt wird und dieser dann ja als erstes zusammenbricht (kürzester Intervall), d.h. die "Zeit" der SmpteFrame wird nicht mehr alle ungefähr 30-40ms erhöht. Im realen Fall kommt das Zeit-Daten Objekt über Netztwerk rein und hat dann natürlich auch die "aktuelle Zeit" bzw. die Zeit die angezeigt werden soll.
Also so krasse Sachen passieren nicht, das ist eine Einstellungssache der Simulation. Wenn ich bei mir WorkOn mit SomeWork count = 20000 habe und die Pegelanzeige ein bzw. aus schalte, dann sehe ich eine etwas schleppendere Anzeige und auf dem J1900 kommt es teilweise zum Stocken.
Auch die Zeiten für die anderen Timer sind ja kürzer als nötig, um überhaupt jetzt mal zum Verständniss einen Unterschied beim umschalten zu sehen. Die zusätzliche Arbeit, die entsteht wenn die Pegel angezeigt werden sind der Punkt. Ob diese zusätzliche Arbeit, durch das Binding im Hintergrund oder weiß nicht genau was da noch passiert, oder aber durch Zusammenspiel DirectX, GPU ... weiß ich nicht.
Die Frage ist, ob das was ich von Packetempfang bis zu den Anzeigen mache so richtig bzw. am besten sogar "optimal" für die Performance ist.
Kannst Du diesen Weg den nachvollziehen, oder soll ich nochmal besser beschreiben?

ps.: rechts unterhalb von der TimeCode Anzeige wird übrigends die verstrichene Zeit je Zeitanzeige Event angezeigt. Also, wenn der Zeitanzeige Timer auf 60 steht, dann sieht man da z.B. dann im guten Fall sowas zwischen 50 und 80. Dient nur dem Verständniss.

Hallo,
will nicht vielleicht doch jemand noch Kritik am Code oder an der vorgehensweise zur Anzeige machen? Ich habe meinen Weg ja jetzt grob beschrieben und die Testapplikation wurde ja schon verschiedentlich herruntergeladen. Es geht nicht um "(=>100% identische Frameraten)" wie behauptet wird, sondern um möglichst performanten Code vom Zeitpunkt des Datenerhalts bis zur Anzeige.
Wenn meine Vorgehensweise so schon in Ordnung ist, wäre das zum einem gut zu erfahren, aber Verbesserungsvorschläge würde ich auch gerne ausprobieren.

Zumindest von meiner Seite nicht... Meine Motivation reicht jetzt nicht aus, mich noch viel genauer damit zu befassen, und ich bin auch kein WPF Experte.
Ich gehe aber davon aus, dass ich das in einer Umgebung, die ich im Griff habe (C++ und Qt) das "besser" hinbekommen würde. Ich vermute auch, dass man das auch mit .NET und WPF besser hinbekommen müsste. Aber ich hatte schon sehr lange nichts mehr mit .NET zu tun und kann jetzt auch nicht endgültig abschätzen, ob WPF oder .NET hier nicht doch zusätzliche Hürden bedeuten.

Mir ist ein Rätsel, was Du hier jetzt für eine Reaktion erwartest.
Du hast binnen der letzten ca. 6 Monate mehrere Hinweise bekommen, aber hast eigentlich Deinen Stiefel durchgezogen.
Bin jetzt auch nochmal über den Thread geflogen.. aber den Eindruck, dass Du davon was ausprobiert hast, hab ich irgendwie nicht.

Ich sehe auch keinen Grund hier weiter hinweise zu geben.
Die Rückmeldungen hast du bekommen aber gekonnt weg ignoriert.
Entsprechend macht es für keinen wirklich Sinn dir weiter Hinweise zugeben, wenn die ignoriert.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

Ich hatte halt noch gehofft, dass jemand der das TestProgramm runtergeladen hat auf Anhieb einen krassen Fehler gesehen hat, aber egal.
Also schonmal vielen Dank an alle die hier schon geduldig Zeit investiert haben oder vielleicht doch noch investieren.
Als derzeitiges Fazit scheint ja der Weg mit den zwei Timern und zwei ConcurrentStack (oder ähnlichem mit manuellen Locking) hier der beste zu sein, wenn man mit c#/.net/WPF/WES7 arbeiten muß. Wie auch hier schon frühzeitig vorgeschlagen. C/C++ mit/ohne Linux mit/ohne Echzeitkernel scheidet von meiner Seite für diese Anwendung leider aus.
Bewußt ignoriert habe ich bestimmt nichts und wenn das so rüber gekommen ist entschuldige ich mich natürlich dafür.

Gruß luciluke

C/C++ mit/ohne Linux mit/ohne Echzeitkernel scheidet von meiner Seite für diese Anwendung leider aus.

Ich möchte nochmal betonen, dass ich erstmal nicht davon ausgehe, dass .NET hier zu langsam wäre und man unbedingt C++ dafür braucht. Mag sein, glaub ich aber erstmal nicht. Ich wollte nur darauf hinaus, dass ich das besser im Griff habe und das Problem dann genauer untersuchen und mehr ausprobieren könnte.

Thema geschlossen