Entwickler-Ecke
WinForms - Performance von mehreren Forms
c_sharp - Mi 24.09.14 11:27
Titel: Performance von mehreren Forms
Hallo,
ich versuche gerade Werte einer SPS in einem Oszilloskop darzustellen. Und zwar stelle ich in bis 4 Forms je ein Chart mit 3 Kurven dar.
Wenn ich jedoch 4 Forms gleichzeitig offen habe, friert die Oberfläche ein.
Eine Messung hat gezeigt, dass ein Programmzyklus ca. 20µs pro Form braucht.
Ist das schon zu langsam? Oder muss ich etwas spezielles beachten,wenn ich mehere Forms gleichzeitg betreiben will.
Ralf Jansen - Mi 24.09.14 11:43
Multiple Formen sind kein Problem. Das was auf der Form ist und das was du auf der Form machst könnte ein Problem sein. Ungesehen ist da wenig zu sagen.
Ich könnte jetzt nur vermuten das dein Verfahren zum holen der Daten und verteilen auf die Charts die Ursache ist oder
eventuell noch die Art wie du das aktualisieren der Charts anstößt (Timer gebastel etc.).
c_sharp - Mi 24.09.14 11:48
Hallo, danke für die schnelle Antwort.
An der Datenübertragung liegt es nicht.
In dem Form habe ich ein Chart von Steema. Über einen Timer starte ich einmal pro Sekunde einen BackroundWorker, in welchem ich das Chart neu zeichne.
Ralf Jansen - Mi 24.09.14 11:59
Zitat: |
Über einen Timer starte ich einmal pro Sekunde einen BackroundWorker, in welchem ich das Chart neu zeichne. |
Da du aus einem anderen Thread nicht einfach Controls aktualisieren darfst wirst du im BackgroundWorker irgendwie den Zugriff auf die UI synchronisieren.
Das solltest du dir genau ansehen wie du das machst und ob du dir da zum Beispiel eine Art Deadlock gebaut hast.
Th69 - Mi 24.09.14 11:59
Hallo,
c_sharp hat folgendes geschrieben: |
Über einen Timer starte ich einmal pro Sekunde einen BackgroundWorker, in welchem ich das Chart neu zeichne. |
Das ergibt aber überhaupt keinen Sinn ;-)
c_sharp - Mi 24.09.14 12:21
Warum nicht?
C#-Quelltext
1: 2: 3: 4: 5: 6: 7:
| if (watch.ElapsedMilliseconds > 1000) { if(!backgroundWorker1.IsBusy) backgroundWorker1.RunWorkerAsync(); watch.Reset(); watch.Start(); } |
Moderiert von
Th69: C#-Tags hinzugefügt
Ralf Jansen - Mi 24.09.14 12:29
Das sieht nicht nach Timer aus sondern nach einer StopWatch :gruebel:
Deine Aussage ist merkwürdig weil
a.) nur der Hauptthread zeichnen kann und in einem anderen Thread maximal die Daten zusammengesucht werden können um sie dann an den Hauptthread zu geben damit der zeichnet
b.) die Kombination aus Timer (womöglich mit einem Thread) und BackgroundWorker (ein Thread) ziemlich überflüssig scheint. Entweder man nimmt einen Threaded Timer und erledigt die Aufgabe im Timer event oder man nimmt einen Thread (zum Beispiel einem Backgroundworker) und läßt ihn rotieren (Schleife die das Timing prüft) und regelmäßig was ausführen.
C# - Mi 24.09.14 12:29
Was führt der Worker denn aus? Dieser Codeteil wäre interessant.
Falls du eine Stopwatch benutzt, kannst du übrigens auch
watch.Restart() schreiben.
PS:
Bei Code bitte Code-Tags verwenden:
Quelltext
1: 2:
| [cs]C# Code hier rein. Geht auch über mehrere Zeilen.[/cs] |
c_sharp - Mi 24.09.14 12:37
Ja ist eine Stopwatch.
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { backgroundWorker1.WorkerReportsProgress = true; backgroundWorker1.ReportProgress(1); } private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { if (this.fastLineSeries1.Count > Convert.ToInt32(AnzeigeWerte) ) this.fastLineSeries1.Delete(0, this.fastLineSeries1.Count - Convert.ToInt32(AnzeigeWerte)); if (this.fastLineSeries2.Count > Convert.ToInt32(AnzeigeWerte) ) this.fastLineSeries2.Delete(0, this.fastLineSeries2.Count - Convert.ToInt32(AnzeigeWerte)); if (this.fastLineSeries3.Count > Convert.ToInt32(AnzeigeWerte) ) this.fastLineSeries3.Delete(0, this.fastLineSeries3.Count - Convert.ToInt32(AnzeigeWerte));
tChart1.AutoRepaint = true; fastLineSeries1.Repaint(); fastLineSeries2.Repaint(); fastLineSeries3.Repaint(); tChart1.AutoRepaint = false; } |
Ich hab gelesen,dass Zugriffe auf Grafikelemente in backgroundWorker1_ProgressChanged gemacht werden sollen.
Th69 - Mi 24.09.14 12:41
Der BackgroundWorker ist doch bei deinem Code überflüssig, da du keine langlaufende Aktion tätigst.
Dann kannst du gleich den im ProgressChanged-Ereignis stehenden Code direkt (im GUI-Thread) ausführen.
Ralf Jansen - Mi 24.09.14 12:41
Denn BackgroundWorker kannst du dir sparen.
Die ~Hintergrund~ Aufgabe gehört in den DoWork Event in dem du aber nichts tust.
ProgressChanged ist bereits wieder synchronisiert in den Hauptthread. Dann kannst du es auch gleich im Hauptthread machen.
C# - Mi 24.09.14 12:45
Also nimm dafür am besten einen WinForms-Timer (der ist schon mit der UI synchronisiert), der im Sekundentakt tickt:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| Timer timer;
void Setup() { timer = new Timer { Interval = 1000 }; timer.Tick += TimerTick; timer.Start(); }
void TimerTick(object sender, EventArgs e) { int wert = int.Parse(AnzeigeWerte); if (fastLineSeries1.Count > wert) fastLineSeries1.Delete(0, fastLineSeries1.Count - wert); if (fastLineSeries2.Count > wert) fastLineSeries2.Delete(0, fastLineSeries2.Count - wert); if (fastLineSeries3.Count > wert) fastLineSeries3.Delete(0, fastLineSeries3.Count - wert);
tChart1.AutoRepaint = true; fastLineSeries1.Repaint(); fastLineSeries2.Repaint(); fastLineSeries3.Repaint(); tChart1.AutoRepaint = false; } |
c_sharp - Mi 24.09.14 12:58
Vielen Dank C#.
So funtioniert es.
Ich habe bei dem BackgroundWorker irgendetwas falsch verstanden, dass muss ich mir nochmal genauer anschauen.
C# - Mi 24.09.14 13:20
Hat das das Performance-Problem gelöst? Kann doch nicht daran gelegen haben :gruebel:
c_sharp - Mi 24.09.14 13:30
Hab mich wohl zu früh gefreut...
Wenn in allen 4 Forms viele Daten dargestellt werden (insgesamt ca. 300.000 Werte) ruckelt die Oberfläche immer noch
Ralf Jansen - Mi 24.09.14 13:38
In was für einem Charttyp kann man denn unterscheidbar 300000 Werte anzeigen?
c_sharp - Mi 24.09.14 13:41
Das ist ein Teechart von der Firma Steema
Ralf Jansen - Mi 24.09.14 13:45
Ok. Aber wie kann es gleichzeitig 300000 Werte darstellen? Bei zum Beispiel einem LineChart macht es wenig Sinn mehr Werte anzuzeigen als die verfügbare Breite in Pixel.
Wenn du das Chartcontrol auf dem gesamten Datenbestand rumkauen lässt würde mich nicht wundern wenn es einfach überfordert ist (mit vorraussichtlich überflüssigen Berechnungen) und daher langsam.
C# - Mi 24.09.14 13:45
Das war wohl eher Ironie von Ralf. Du kannst in keinem Chart 300.000 Werte anzeigen. Wer soll die denn auswerten bzw. ablesen? Nur weil du 300.000 Datensätze hast, musst du die doch nicht alle anzeigen. Das ist nämlich ein Performancefresser.
Rechne die Daten lieber auf Mittelwerte runter.
Sagen wir du willst 300 Werte anzeigen, dann nimmst du immer 1000 Werte und berechnest den Durchschnitt daraus. Und diese Durchschnittswerte übergibst du dann deinem Chart.
/// Nachtrag
Verdammt. Schon wieder zu langsam :mrgreen:.
Stell dir mal vor du musst eine 0.1mm lange Linie zeichnen mit einem Stift, dessen Miene 2mm dick ist. Dann weißt du wie sie die Graphics-Einheit der Chart fühlt :D
c_sharp - Mi 24.09.14 13:52
Ich will aber die Werte der SPS anzeigen (z.B. Soll und Istposition). Wenn ich jetzt Werte weg lasse oder den Mittelwert berechne habe ch ja nichts gewonnen, da ich zum Bsp. Picks übersehe.
Und ja es sind viele Werte. Im Moment sind es 12 Variablen, die Zykluszeit des SPS ist 200µs und die Anzeigezeit pro Chart liegt irgendwo bei 30-50 sec.
c_sharp - Mi 24.09.14 14:16
Meint ihr das geht oder schafft C# die Datenmenge einfach nicht.
Ralf Jansen - Mi 24.09.14 14:32
Ich bin immer noch am Punkt das ein Bildschirm soviel nicht darstellen kann. Und du viele deiner 300000 Daten möglichweise mehrmals auf die gleichen Pixel projezierst was unnötiger Aufwand ist. Letztlich läuft es darauf hinaus was das von dir gewählte Control intern mit den Daten macht. Unabhängig davon in welcher Sprache es dies tut.
Bei den Internas bist du dann aber beim Support des Control Herstellers. Unabhängig von denen ist dir kaum zu helfen außer eben mit dem Hinweis das du vorraussichtlich unnötiges weglassen solltest und dem Control nur Daten unterjubeln solltest die es auch sinnvoll auf der zur Verfügung stehenden Fläche darstellen kann.
c_sharp - Mi 24.09.14 14:34
Ok jetzt versteh ich was du meinst.
Bei dem Teechart ist eine Funkiton aktiviert, welche Messpunkte die auf dem gleichen Pixel dargestellt werden weggelassen
Blup - Mi 24.09.14 15:32
Vereinfacht zusammengefasst:
Angenommen dein Chart kann 300 Werte unterscheidbar nebeneinander darstellen.
Du hast aber 300000 Messpunkte.
Dich interessieren die Grenzwerte.
Also berechnest du für jeweils 1000 Messpunkte den höchsten und den niedrigsten Wert und zeichnest so zwei Linien auf dem Chart.
Optional wäre dann der Mittelwert für 1000 Messpunkte die dritte Linie.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!