Forum: PC-Programmierung Performante Gui durch eigenen Thread?


von Otto (Gast)


Lesenswert?

Ich möchte eine performante Gui in Qt schreiben.
Und im Hintergrund sollen per Ethernet Nachrichten empfangen werden, die 
dann in der Gui angezeigt werden.
Sollte ich die Empfangsfunktion in einen eigenen Thread auslagern?

Bzw. wann sollte man Funktionen in eigene Threads auslagern?

von Oliver (Gast)


Lesenswert?

Sollen sollen sollst du gar nichts, und müssen müssen mußt du auch 
nichts, aber können können könntest du das tun.

Das qt aber eigentlich alles für sich erledigt, brauchst du nur auf die 
passenden Signale zu reagieren.

Oliver

von Otto (Gast)


Lesenswert?

Aber wenn ich alle 10 ms eine Nachricht aus dem Ethernet Stack kommt 
wird die Gui doch möglichen zu langsam!

von Meister E. (edson)


Lesenswert?

Otto schrieb:
> Aber wenn ich alle 10 ms eine Nachricht aus dem Ethernet Stack kommt
> wird die Gui doch möglichen zu langsam!

Und was würde der Benutzer für Vorteile daraus ziehen, wenn er alle 10ms 
neue Informationen gezeigt bekommt? Keine, weil er die Informationen so 
schnell gar nicht erfassen kann. Also existiert dein Problem nur in 
deiner Vorstellung, stimmts?

von Olaf D. (Firma: O.D.I.S.) (dreyero)


Lesenswert?

Nein, die Frage des TO ist durchaus berechtigt.
Ich habe das gleiche Problem dadurch gelöst,
dass ich die (in meinem Fall bis zu 4000 Nachrichten / s) in einem 
eigenen
Thread empfange und dekodiere, sie an die GUI weiterreiche und dort 
zwischenspeichere. Alle 300ms wird der Speicher (eine QList o. ä.) 
ausgelesen und die GUI aktualisiert (bis zu 10000 Zeilen).

Gruß

Olaf

: Bearbeitet durch User
von TriHexagon (Gast)


Lesenswert?

Olaf Dreyer schrieb:
> Thread empfange und dekodiere, sie an die GUI weiterreiche und dort
> zwischenspeichere. Alle 300ms wird der Speicher (eine QList o. ä.)
> ausgelesen und die GUI aktualisiert (bis zu 10000 Zeilen).

Und wie soll der Benutzer 10000 Zeichen / 300 ms lesen können?
Was soll das bringen?

von Olaf D. (Firma: O.D.I.S.) (dreyero)


Lesenswert?

Ich schrieb Zeilen, nicht Zeichen.
Wenn ich z. B. ein Autoradio teste das per Ethernet seine Traceausgaben 
schickt, dann kan ich schon bei der Änderung der einzelnen Testparameter 
erkennen, ob das Gerät vermehrt Fehlermeldungen ausspuckt. Solche werden 
natürlich an der GUI durch SyntaxHighlighting hervorgerufen.

Gruß

Olaf

von Olaf D. (Firma: O.D.I.S.) (dreyero)


Lesenswert?

Und zur genaueren Analyse schaut man dann in die Datei, in der die 
Messages parallel gestreamt wurden.

Nochmals Gruß

Olaf

von Olaf D. (Firma: O.D.I.S.) (dreyero)


Lesenswert?

Ich meinte natürlich im vorletzten Beitrag:
Solche werden natürlich an der GUI durch SyntaxHighlighting 
hervorgehoben.

Gruß

Olaf

von Otto (Gast)


Lesenswert?

Meister Eder schrieb:
> Und was würde der Benutzer für Vorteile daraus ziehen, wenn er alle 10ms
> neue Informationen gezeigt bekommt? Keine, weil er die Informationen so
> schnell gar nicht erfassen kann. Also existiert dein Problem nur in
> deiner Vorstellung, stimmts?


Hallo,

du hast recht der Benutzer kann die Inforamtion so schnell nicht 
erfassen.
Aber angenommen ich ersetzt den Ethernet Stack durch einen Can-Stack.
Hierbei empfängt mein Anzeigegerät Prozessdaten mit hoher 
Geschwindigkeit (alle 10 ms). Wie kann ich verhindern, dass mein Gerät 
nicht ständig damit beschäftigt ist, Nachrichten zu empfangen?

von Sven B. (scummos)


Lesenswert?

Die GUI kannst bzw. solltest du nicht in einen Thread schieben. Du 
kannst aber, wie bereits gesagt wurde, zeitaufwändige Aufgaben in einem 
eigenen Thread machen. Aber wie immer bei Threads ist die Frage, ob das 
a) tatsächlich schneller ist im Endeffekt und b) den Aufwand lohnt. Mein 
Rat wäre, es zuerst ohne zu versuchen, und die Thread-Variante nur zu 
probieren wenn's tatsächlich zu langsam ist.

Grüße,
Sven

von Oliver (Gast)


Lesenswert?

Otto schrieb:
> Wie kann ich verhindern, dass mein Gerät
> nicht ständig damit beschäftigt ist, Nachrichten zu empfangen?

Gar nicht, und da liegt auch dein Denkfehler. Wenn die ganze verfügbare 
Rechenzeit dafür drauf geht, Daten zu empfangen, dann hilft ein 
zusätzlicher Thread auch nicht weiter. Mehr verfügbare Rechenzeit 
bekommst du dadurch nicht. Außer natürlich, bei einem Mehrkernprozessor 
liegen Kerne brach, die durch einen zusätzlichen Tthread genutzt werden 
können.

Oliver

von Sven B. (scummos)


Lesenswert?

Das ist Unfug. Die GUI zu verwalten braucht nur sehr wenig Zeit, und 
selbst wenn die CPU fast komplett mit dem Verarbeiten von irgendwas 
beschäftigt ist, ist es kein Problem währenddessen noch einen 
Fortschrittsbalken anzuzeigen oder was auch immer.

von Otto (Gast)


Lesenswert?

Sven B. schrieb:
> Das ist Unfug. Die GUI zu verwalten braucht nur sehr wenig Zeit,
> und
> selbst wenn die CPU fast komplett mit dem Verarbeiten von irgendwas
> beschäftigt ist, ist es kein Problem währenddessen noch einen
> Fortschrittsbalken anzuzeigen oder was auch immer.

Ein Fortschrittsbalken ist kein Problem.
Allerdings soll auch navigiert und gescrollt werden können. Und das 
kostet CPU Leistung.

von Sven B. (scummos)


Lesenswert?

Wenn man es richtig macht nicht viel.

von Otto (Gast)


Lesenswert?

Sven B. schrieb:
> Wenn man es richtig macht nicht viel.

Wie macht man es richtig?

von Sven B. (scummos)


Lesenswert?

Kommt halt drauf an, was man genau anzeigen will. Insbesondere halt 
darauf achten, dass nur so oft gerendert wird wie das auch sinnvoll ist, 
dass das effizient geschieht, und dass insbesondere nur auf die dazu 
nötigen Daten zugegriffen wird und nicht auf alle. Es gibt genug 
Anwendungen, die das ordentlich vormachen, ein typischer 
Terminal-Emulator zum Beispiel kann problemlos zehntausende Zeilen Text 
rendern während eine in ihm ausgeführte Anwendung die CPU quasi komplett 
auslastet.

von Christian B. (casandro)


Lesenswert?

Was effizienter ist, hängt wirklich von den Details ab, aber wenn ein 
Datenstrom reinkommt, kann ein Thread der dann auf dem Socket blockiert 
durchaus die sinnvollste Möglichkeit sein. Man muss da halt überlegen 
wie man das mit dem Rest des Programmes synchronisiert.


Aber, für Fehlermeldungen eines Gerätes braucht man eine GUI Software. 
So was macht man entweder ganz einfach per TCP-Socket quasi per Telnet, 
oder per UDP in einem Syslog kompatiblen Format. Dadurch wird die "GUI" 
zu einem einfachen
netcat <DUT-IP> <PORT> > <Dateiname> &
tail -f <Dateiname>

von Bernd K. (prof7bit)


Lesenswert?

Sven B. schrieb:
> a) tatsächlich schneller ist im Endeffekt und b) den Aufwand lohnt.

Das Problem ist ja weniger die Ausführungsgeschwindiogkeit sondern die 
Frage ob die GUI noch zügig auf Mausereignisse reagiert während im 
Hintergrund noch was anderes gemacht wird. Es gibt nichts störenderes 
als eine GUI die einen Klick nicht augenblicklich entgegennimmt 
sondern stattdessen wie eingefroren erscheint.

Ein separater Thread is weniger Aufwand, nicht mehr. Wenn Du alles im 
Main-Thread machen willst musst Du aberwitzige Verrrenkungen anstellen 
um gleichzeitig noch die GUI-Eventloop am laufen zu halten, ein separate 
Thread jedoch läuft einfach so für sich und kann sich voll auf das 
konzentrieren wozu er da ist und auch mal 99% seiner Zeit in nem 
blockierenden read() stecken ohne sich um den Rest der Anwendung 
irgendwelche Gedanken machen zu müssen. Das ist wesentlich einfacher zu 
handhaben.

: Bearbeitet durch User
von Sven B. (scummos)


Lesenswert?

Es kommt halt immer auf den konkreten Fall an. In dieser Allgemeinheit 
lässt sich die Fragestellung nicht diskutieren. Klar, wenn du mit einer 
synchronen API zu tun hast die auch mal länger braucht, führt um einen 
extra-Thread wohl kein Weg herum.

von Purzel H. (hacky)


Lesenswert?

Ich wuerde den extra thread fuer den externen Prozess verwenden.

von c.m. (Gast)


Lesenswert?

Siebzehn Zu Fuenfzehn schrieb:
> Ich wuerde den extra thread fuer den externen Prozess verwenden.

dito. ohne qt zu kennen finde ich daß das schnelle datenfetchen und die 
gui nicht "in die selbe loop" gehören. das sind zwei unterscheidliche 
dinge - die gui soll "in echtzeit" auf nutzereingaben reagieren, und der 
fetcher soll genügend cpu-cycles haben um seiner aufgabe nachzukommen.
wer kennt nicht mindestens ein programm das nicht reagiert weil es beim 
datenverarbeiten nicht mehr auf den gedrückten abbrechen button 
reagiert…?

von Sven B. (scummos)


Lesenswert?

Es kommt halt drauf an. Wenn du eh einen externen Prozess startest und 
alles was du mit dem tust ist seine Ausgabe in einem Textfeld 
darzustellen dann bringt dir der extra-Thread genau gar nichts, der 
macht alles nur schlechter und komplizierter. Der extra-Thread bringt in 
dem Fall nur was, wenn du sehr rechenaufwendiges Post-Processing mit dem 
Output von dem Prozess machst.

von Bernd K. (prof7bit)


Lesenswert?

Sven B. schrieb:
> Es kommt halt drauf an. Wenn du eh einen externen Prozess startest

Wo steht da daß er nen separaten Prozess startet? Er will 
Netzwerk-Kommunikation machen und das macht man traditionell mit nem 
separaten Thread, das ist sauber, übersichtlich, wesentlich einfacher zu 
handhaben und ist in 3 Minuten hingeschrieben. Dazu braucht man:

* die API-Funktion um einen Thread zu starten (1 Zeile Code)
* while (!terminated) {
* den Code um vom Socket zu lesen (braucht er sowieso)
* Empfangenes Paket da hinschreiben wo es der Main Thread abholen kann
* Mit Main-Thread synchronisieren (1 Zeile)
* }

von Nase (Gast)


Lesenswert?

Bernd K. schrieb:
> Sven B. schrieb:
>> Es kommt halt drauf an. Wenn du eh einen externen Prozess startest
>
> Wo steht da daß er nen separaten Prozess startet? Er will
> Netzwerk-Kommunikation machen und das macht man traditionell mit nem
> separaten Thread,
Wusste ich garnicht. Muss da was verpasst haben.

> das ist sauber, übersichtlich, wesentlich einfacher zu
> handhaben und ist in 3 Minuten hingeschrieben.
Ah ja.

> Dazu braucht man:
>
> * die API-Funktion um einen Thread zu starten (1 Zeile Code)
> * while (!terminated) {
> * den Code um vom Socket zu lesen (braucht er sowieso)
> * Empfangenes Paket da hinschreiben wo es der Main Thread abholen kann
> * Mit Main-Thread synchronisieren (1 Zeile)
> * }
Ok, und jetzt erklärst du uns bitte noch etwas über 'volatile' und die 
Synchronisation. Ich bin mir recht sicher, dass es auf einmal doch mehr 
als 3 Minuten braucht, wenn man sich bemüht, keine ranzige Müllware zu 
programmieren.

Und schließlich sollte man noch klären, warum überhaupt der 
Datenempfang so tödlich für die GUI ist. Meistens kommt dabei nämlich 
heraus, dass der Thread nur eine faule Ausrede dafür ist, dass man keine 
sauberen Zustandsautomaten programmieren kann/will.

von Otto (Gast)


Lesenswert?

Nase schrieb:
> Meistens kommt dabei nämlich
> heraus, dass der Thread nur eine faule Ausrede dafür ist, dass man keine
> sauberen Zustandsautomaten programmieren kann/will.

Was würde denn so ein "sauberer Zustandsautomat" prinzipiell machen ?

von Nase (Gast)


Lesenswert?

Otto schrieb:
> Was würde denn so ein "sauberer Zustandsautomat" prinzipiell machen ?

Daten empfangen, wenn es welche zu empfangen gibt und verarbeiten, wenn 
es was zu verarbeiten gibt. Der Zustandsautomat ersetzt damit die 
lineare Verarbeitung, die man faul in einen Thread reinklatscht. Der 
Automat dagegen blockiert nicht, sondern muss nur regelmäßig angestoßen 
(aufgerufen) werden.

Wenn man nicht gerade auf einem Mehrkernsystem arbeitet, wird es nämlich 
durch einen Thread nicht effizienter, weil auch der Thread keine 
zusätzliche Rechenzeit herbeizaubert. Man muss sich eben Gedanken 
machen, wie oft man den Automaten anstößt und wie oft (dazwischen) man 
die Eventloop der GUI anstößt. Und das wird auch mit einem Thread nicht 
besser.

Wenn der Thread gerade in einer atomaren Operation festhängt, dann ist 
das Scheduling nämlich auch im Eimer und die GUI friert ein. Präemptives 
Scheduling macht nämlich auch nichts anderes, als den Programmfluss an 
einer (geeigneten) Stelle abzuwürgen und umzuschalten.

von Otto (Gast)


Lesenswert?

Aber was passiert, wenn ständig Daten verarbeitet werden müssen?
-> Der Nachrichtenpuffer muss ausgelesen werden, damit er nicht 
überläuft.
-> Es werden alle 10 ms Nachrichten in den Puffer geschrieben.

von Nase (Gast)


Lesenswert?

Otto schrieb:
> Aber was passiert, wenn ständig Daten verarbeitet werden müssen?
> -> Der Nachrichtenpuffer muss ausgelesen werden, damit er nicht
> überläuft.
> -> Es werden alle 10 ms Nachrichten in den Puffer geschrieben.
Und was passiert, wenn du das mit Threads machst?

von Otto (Gast)


Lesenswert?

Ich weis das ich dadurch nicht mehr Rechenzeit bekommen.
Aber was soll ich sonst machen?
Den Puffer auslesen und die Hälfte aller Nachrichten gleich verwerfen?

von ?!? (Gast)


Lesenswert?

Otto schrieb:
> Ich weis das ich dadurch nicht mehr Rechenzeit bekommen.
> Aber was soll ich sonst machen?
> Den Puffer auslesen und die Hälfte aller Nachrichten gleich verwerfen?

Um die Frage beantworten zu können, mußt du dir nur überlegen, ob das 
auslesen mehr als 10ms dauert. Wenn nicht, kannst du den Rest der Zeit 
für die GUI verwenden. Muß ja nicht am Stück sein, die Zeit kann man 
sich ja mittels Statemachine aufteilen. Wenn das Auslesen aber wirklich 
länger als 10ms dauern sollte und die Nachrichten kommen aller 10ms 
rein, dann kannst du, wie du schon gesagt hast, keine Rechenzeit 
herbeizaubern.

von Nase (Gast)


Lesenswert?

Otto schrieb:
> Ich weis das ich dadurch nicht mehr Rechenzeit bekommen.
> Aber was soll ich sonst machen?
> Den Puffer auslesen und die Hälfte aller Nachrichten gleich verwerfen?
Das musst du schon selbst beantworten. Aber du erkennst ja, dass es mit 
einem Thread nicht besser wird. Eher schlechter wegen der 
Kontextwechsel.

Wenn du mit dem Auswerten nicht hinterherkommst, kannst du die GUI 
vernachlässigen um dort Rechenzeit zu sparen. Natürlich friert die dann 
ein. Wenn du dann immer noch nicht hinterherkommst, dann wirst du wohl 
Nachrichten verwerfen müssen.

Wenn die Auswertung aber (zeitlich) teuer ist aber die Zeit der 
Erfassung nur begrenzt ist, dann könntest du die Nachrichten während der 
Erfassung unbewertet in einen großen Puffer schreiben und dann 
anschließend in Ruhe auswerten?

von Aloha (Gast)


Lesenswert?

> Muß ja nicht am Stück sein, die Zeit kann man
> sich ja mittels Statemachine aufteilen. Wenn das Auslesen aber wirklich
> länger als 10ms dauern sollte und die Nachrichten kommen aller 10ms
> rein
...
> Man muss sich eben Gedanken
> machen, wie oft man den Automaten anstößt und wie oft (dazwischen) man
> die Eventloop der GUI anstößt.
...

Klar, möglichst fummelig, low-level und kaum sinnvoll skalierbar.

> Eher schlechter wegen der Kontextwechsel.

Das Unterforum hier heißt PC-Programmierung, nicht uC-Programmierung.

> dann kannst du, wie du schon gesagt hast, keine Rechenzeit
> herbeizaubern.
...
> wird es nämlich durch einen Thread nicht effizienter, weil auch der
> Thread keine zusätzliche Rechenzeit herbeizaubert.

Bevor man Ratschläge gibt, solle man evtl. erst einmal den Unterschied 
zwischen I/O-bound und CPU-bound kennen ...

von Nase (Gast)


Lesenswert?

Aloha schrieb:
> Bevor man Ratschläge gibt, solle man evtl. erst einmal den Unterschied
> zwischen I/O-bound und CPU-bound kennen ...
Hast du außer Genörgel auch noch etwas beizutragen, was den OT irgendwie 
weiterbringt? Ansonsten solltest du vielleicht zuerst das ganze Thema 
lesen.

Aber gottseidank - ja GOTTSEIDANK - skalieren Threads genau bei diesem 
Problem hier so ausgezeichnet gut.

Geh doch bitte wieder Java-Bloat spielen.

von ?!? (Gast)


Lesenswert?

Aloha schrieb:
> Klar, möglichst fummelig, low-level und kaum sinnvoll skalierbar.

Was ist bitte an einer Statemachine "fummelig, low-level und kaum 
sinnvoll skalierbar"? Das weißt bestimmt nur du allein. ;-)

von Sven B. (scummos)


Lesenswert?

Das ist nicht fummelig. In Qt benutzt du zum Beispiel QTcpSocket und 
verbindest dich mit dem readyRead()-Signal. Das in einem Thread zu 
machen bringt so gut wie nichts, außer du willst halt wie gesagt 
rechenaufwändiges Post-Processing machen.

von Nase (Gast)


Lesenswert?

Sven B. schrieb:
> Das ist nicht fummelig. In Qt benutzt du zum Beispiel QTcpSocket und
> verbindest dich mit dem readyRead()-Signal.
Zum Beispiel, genau.
Und was hast du dann? Richtig: Einen Zustandsautomaten. Denn nichts 
anderes ist das QT-Eventzeugs nämlich.

> Das in einem Thread zu
> machen bringt so gut wie nichts, außer du willst halt wie gesagt
> rechenaufwändiges Post-Processing machen.
Und selbst da bringt der Thread nichts, wenn keine Rechenzeit mehr da 
ist oder wenn der Scheduler die beiden Threads auf dieselbe CPU packt. 
Außer, dass man sich noch um die Synchronisierung kümmern muss.
Ok, QT-Signale gehen auch threadsicher, aber einfacher wirds auch nicht.

von Sven B. (scummos)


Lesenswert?

Nase schrieb:
> Sven B. schrieb:
>> Das ist nicht fummelig. In Qt benutzt du zum Beispiel QTcpSocket und
>> verbindest dich mit dem readyRead()-Signal.
> Zum Beispiel, genau.
> Und was hast du dann? Richtig: Einen Zustandsautomaten. Denn nichts
> anderes ist das QT-Eventzeugs nämlich.

Jo, klar, hat auch niemand was gegenteiliges behauptet :-)

von Bernd K. (prof7bit)


Lesenswert?

Nase schrieb:
> Wenn man nicht gerade auf einem Mehrkernsystem arbeitet, wird es nämlich
> durch einen Thread nicht effizienter

Nochmal zum Mitschreiben: Es geht nicht darum ob es effizienter wird 
denn nichts davon ist CPU-bound sondern es geht darum daß es mit einem 
separaten Thread simpler, aufgeräumter, unkomplizierter, weniger Code 
und einfacher wartbar wird.

Separation of concerns. Das GUI hat nicht im Netzwerk herumzufuhrwerken, 
es hat 100% seiner Zeit auf die Maus und die Tastatur zu warten und ab 
und zu mal Teile der Fenster neu zu malen und sonst nichts.

Ach und das hat übrigens auch nichts mit "volatile" zu tun und 
Synchronize() ist bei mir eine Zeile Code (und eine Handler-Funktion auf 
der anderen Seite) und wenns Asynchron laufen soll dann gibts dafür 
ebenfalls simple Mechanismen, jedes Framework das ich bis jetzt gesehen 
habe bringt solche Mechanismen schon mit und das Framework das OP 
verwendet mit Sicherheit ebenfalls.

von Sven B. (scummos)


Lesenswert?

Bernd K. schrieb:
> sondern es geht darum daß es mit einem
> separaten Thread simpler, aufgeräumter, unkomplizierter, weniger Code
> und einfacher wartbar wird.
Das ist meiner Meinung nach definitiv falsch. Wahrscheinlich 80% aller 
Bugs haben irgendwas mit Threads zu tun, und die vermeidet man am 
einfachsten, indem man keine Threads hat wenn es irgendwie geht. Mit 
aufgeräumtem Code hat das überhaupt nichts zu tun (warum sollte es?).

: Bearbeitet durch User
von Bernd K. (prof7bit)


Lesenswert?

Sven B. schrieb:
> 80% aller
> Bugs haben irgendwas mit Threads zu tun,

Nachweis?

> und die vermeidet man am
> einfachsten, indem man keine Threads hat wenn es irgendwie geht.

Ich weiß nicht welche Probleme manche Leute mit Threads haben, es gibt 
ein paar Sachen die man beachten muß, aber das muß man bei tausend 
anderen Designpatterns ebenfalls, Threads per se sind auch nicht 
irgendwie inherent komplizierter als alles andere. Und sie helfen 
oftmals verschiedene Abläufe die vollkommen unabhängig voneinander (auch 
und vor allem zeitlich) ablaufen sollen sauber voneinander zu 
entkoppeln. Im Wesentlichen muss man lediglich an der einen kleinen 
Stelle aufpassen an der zwei Threads miteinander Informationen 
austauschen und dafür gibts klare und bewährte Vorgehensweisen. In dem 
Beispiel mit einem GUI-Thread und einem Netwerk-Thread wäre das absolut 
trivial.

von Sven B. (scummos)


Lesenswert?

Bernd K. schrieb:
> Nachweis?
In der Anwendung in der ich da ein bisschen den Überblick habe durch was 
Crashes verursacht werden ist das so.

> In dem
> Beispiel mit einem GUI-Thread und einem Netwerk-Thread wäre das absolut
> trivial.
Threads sind viele Dinge, aber nach meiner Erfahrung nie trivial. 
Vielleicht bin ich auch einfach nur doof, aber ich finde den ganzen 
Thread-Kram im Detail sehr kompliziert und sehr leicht falsch zu machen.

von Snicky (Gast)


Lesenswert?

Sven B. schrieb:
> Threads sind viele Dinge, aber nach meiner Erfahrung nie trivial.
> Vielleicht bin ich auch einfach nur doof, aber ich finde den ganzen
> Thread-Kram im Detail sehr kompliziert und sehr leicht falsch zu machen.

Dann benutzt du die falsche Programmiersprache ;-))

von Nase (Gast)


Lesenswert?

Bernd K. schrieb:
> Nase schrieb:
>> Wenn man nicht gerade auf einem Mehrkernsystem arbeitet, wird es nämlich
>> durch einen Thread nicht effizienter
>
> Nochmal zum Mitschreiben: Es geht nicht darum ob es effizienter wird
> denn nichts davon ist CPU-bound sondern es geht darum daß es mit einem
> separaten Thread simpler, aufgeräumter, unkomplizierter, weniger Code
> und einfacher wartbar wird.
Die meisten Programme scheitern ja schon daran, sauber aus einem 
blockierten Aufruf heraus abzubrechen.

'Separation of concerns' geht wunderbar ohne Threads. Es geht auch 
wunderbar mit Threads. Aber so wie der OT sein Problem bislang umrissen 
hat, würde ich mich in diesem Fall nicht freiwillig Threads antun.

Vorallem 'synchronize' in Java ist immer wieder lustig. Selbst in der 
Doku hat man das schon erkannt ('be very careful') ...

von Bernd K. (prof7bit)


Lesenswert?

Nase schrieb:
> würde ich mich in diesem Fall nicht freiwillig Threads antun.

Wieso antun? Ich empfinde Threads als eine nützliche Erweiterung meiner 
Werkzeugkiste die ich gerne anwende wenn es sich anbietet (so wie im 
vorliegenden Falle). Schließlich stellen Threads ja keinen Mehraufwand 
dar (im Gegenteil) und übersichtlicher und modularer wirds dadurch auch 
;-)

: Bearbeitet durch User
von Sven B. (scummos)


Lesenswert?

Bernd K. schrieb:
> Wieso antun? Ich empfinde Threads als eine nützliche Erweiterung meiner
> Werkzeugkiste die ich gerne anwende wenn es sich anbietet (so wie im
> vorliegenden Falle). Schließlich stellen Threads ja keinen Mehraufwand
> dar (im Gegenteil) und übersichtlicher und modularer wirds dadurch auch
> ;-)

Und genau diese Vorgehensweise halte ich für nicht zielführend. Threads 
sind nichts was man einfach mal so über eine Anwendung drüberstreut, 
weil man das halt kann, sondern man sollte die nur einsetzen, wenn man 
einen sehr guten Grund dafür hat. Und "meine Anwendung wird dadurch 
modularer" ist definitiv kein Grund. Das kannst du ganz genau so auch 
ohne Threads machen.

von Robert L. (lrlr)


Lesenswert?

man könnte auch einfach nicht jedes mal das Rad neu erfinden, und eine 
Biliothek verwenden die das schon mit threads macht..(was wohl eh alle 
machen) (sowas wirds ja wohl auch für Qt geben?)

von Sven B. (scummos)


Lesenswert?

Die was genau mit Threads macht?

von Robert L. (lrlr)


Lesenswert?

was?
na genau das was der TO will

>Und im Hintergrund sollen per Ethernet Nachrichten empfangen werden,

von Sven B. (scummos)


Lesenswert?

Mir ist nicht klar wozu man dazu einen Thread braucht. Der Kernel füllt 
doch so einen Buffer und schickt dir ein Event wenn der voll ist, oder?

von Tobias K. (t_k)


Lesenswert?

Hab nur bis zur Hälfte mitgelesen, aber ich hol mir jetzt erstmal 
Popcorn.
Die Diskussionen sind ja filmreif! :)
Bitte weiter so.

von Bernd K. (prof7bit)


Lesenswert?

Sven B. schrieb:
> Der Kernel füllt
> doch so einen Buffer und schickt dir ein Event wenn der voll ist, oder?

Nein.

von Sven B. (scummos)


Lesenswert?

Bernd K. schrieb:
> Sven B. schrieb:
>> Der Kernel füllt
>> doch so einen Buffer und schickt dir ein Event wenn der voll ist, oder?
>
> Nein.

Sondern?

von Bernd K. (prof7bit)


Lesenswert?

Sven B. schrieb:
> Bernd K. schrieb:
>> Sven B. schrieb:
>>> Der Kernel füllt
>>> doch so einen Buffer und schickt dir ein Event wenn der voll ist, oder?
>>
>> Nein.
>
> Sondern?

Du wartest auf das Event.

von Sven B. (scummos)


Lesenswert?

Bernd K. schrieb:
>>> Nein.
>>
>> Sondern?
>
> Du wartest auf das Event.

Ich warte nicht aktiv auf das Event. Das steht in irgendeiner 
Warteschlange und ich arbeite es ab wenn ich Lust dazu habe.

von Bernd K. (prof7bit)


Lesenswert?

Sven B. schrieb:
> Bernd K. schrieb:
>>>> Nein.
>>>
>>> Sondern?
>>
>> Du wartest auf das Event.
>
> Ich warte nicht aktiv auf das Event. Das steht in irgendeiner
> Warteschlange und ich arbeite es ab wenn ich Lust dazu habe.

Scroll mal nach oben: Es geht um "performant". Das ist inkompatibel mit 
"wenn ich Lust dazu habe". Und wenn Du eh nur pollen willst wenn Du 
gerade mal wieder ein bisschen Lust hast dann brauchst Du auch kein 
Event.

von Sven B. (scummos)


Lesenswert?

Es geht um "performant" im Sinne von "weniger als 20ms Reaktionszeit". 
Da ist es völlig ok, wenn das Event abgearbeitet wird, wenn die Event 
Loop das nächste mal ausgeführt wird.

von Bernd K. (prof7bit)


Lesenswert?

Sven B. schrieb:
> Es geht um "performant" im Sinne von "weniger als 20ms Reaktionszeit".
> Da ist es völlig ok, wenn das Event abgearbeitet wird, wenn die Event
> Loop das nächste mal ausgeführt wird.

Ach, machs doch so Du willst.

OP hat sich wahrscheinlich eh schon längst verabschieded und ich bin 
(und bleibe) ein Befürworter von modularem Design und loser Kopplung und 
alles was autonom funktionieren kann soll auch autonom funktionieren und 
schön gekapselt und austauschbar sein und wenn das Ding zur Erfüllung 
seiner internen Aufgaben auf Events warten muss dann bekommt es eben mal 
intern seinen eigenen Thread, warum denn auch nicht?

Man könnte fast meinen manchen Leuten wurde irgendwann in den letzten 4 
Jahren eingetrichtert daß Nebenläufigkeit generell vom Teufel erfunden 
wurde. Ist das etwa die JavaScript-Fraktion, jene Leute die spätestens 
seit node überall nur noch Nägel für ihren (einen) Hammer sehen, die 
erfolgreich für sich den Mangel zum Feature umdefiniert haben?

Mann mann mann, allein in der Zeit die dieser unselige Thread hier jetzt 
schon diskutiert wird hätte man einen ganzen Threadpool schreiben 
können.

von Sven B. (scummos)


Lesenswert?

Bernd K. schrieb:
> OP hat sich wahrscheinlich eh schon längst verabschieded und ich bin
> (und bleibe) ein Befürworter von modularem Design und loser Kopplung und
> alles was autonom funktionieren kann soll auch autonom funktionieren und
> schön gekapselt und austauschbar sein und wenn das Ding zur Erfüllung
> seiner internen Aufgaben auf Events warten muss
... was, zum n-ten mal, überhaupt nichts mit Threads zu tun hat. Nichts. 
Außer vielleicht dem letzten Teil mit den Events wenn die Events 
irgendwie synchron ankommen. Was aber zum Beispiel bei Input-Events 
nicht der Fall ist.

> dann bekommt es eben mal
> intern seinen eigenen Thread, warum denn auch nicht?
"intern"? Den sehe ich sogar in meinem Task-Manager, wenn ich deine 
Anwendung ausführe. Und warum nicht? Weil es im Zweifelsfall leicht mal 
schlechtere Performance mit sich bringt (Kontextwechsel!) und die 
Komplexität der Anwendung erhöht, wenn man einfach nur so ein paar 
Threads über die Anwendung streut "weil man es kann".

: Bearbeitet durch User
von Bernd K. (prof7bit)


Lesenswert?

Sven B. schrieb:
> und die
> Komplexität der Anwendung erhöht,

Zum n-ten Mal: nein. Siehe oben. Pollen ist inakzeptabel und 
unperformant, da sind sich ja wohl alle einig. Was schlägst Du also vor?

Lass Dir Zeit mit der Antwort, ich hau mich jetzt aufs Ohr.

: Bearbeitet durch User
von Nase (Gast)


Lesenswert?

Bernd K. schrieb:
> Pollen ist inakzeptabel und
> unperformant, da sind sich ja wohl alle einig.
Nein, genau da ist sich keiner hier einig.
Einzig du allein hast Pollen grundlos als inakzeptabel hingestellt.

von Bernd K. (prof7bit)


Lesenswert?

Nase schrieb:
> Nein, genau da ist sich keiner hier einig.

Hier vielleicht nicht, in Fachkreisen jedoch schon. Und deshalb klinke 
ich mich an dieser Stelle mal hier aus, das führt eh zu nichts.

von Oliver (Gast)


Lesenswert?

Um mal auf das Thema zurückzukommen: Immerhin geht es hier ja um Qt. Zum 
Thema "Performantes GUI" gibt's da ja nun schon einiges an Doku, und 
auch zum Thema Threads. Der TO muß da also einfach nur mal nachlesen.

So als Einstieg:
http://qt-project.org/doc/qt-5/thread-basics.html#when-to-use-alternatives-to-threads

Oliver

von Sven B. (scummos)


Lesenswert?

Bernd K. schrieb:
> Nase schrieb:
>> Nein, genau da ist sich keiner hier einig.
>
> Hier vielleicht nicht, in Fachkreisen jedoch schon. Und deshalb klinke
> ich mich an dieser Stelle mal hier aus, das führt eh zu nichts.

Oooh, in "Fachkreisen", soso!

Mit Polling hat das doch alles nix zu tun. Der Unterschied ob man das 
Event-Handling im GUI-Thread macht oder nicht ist einfach nur der: im 
ersten Fall kommt das Event (z.B. "neuer Kram aus dem Netzwerk 
angekommen") in der Event-Loop vom GUI-Thread an; im zweiten Fall hast 
du einen zweiten Thread, der selber eine Event Loop hat, und das Event 
kommt dort an, und der Kernel wechselt zwischen den beiden Loops hin und 
her. Das ist in dem Fall absolut kontraproduktiv.

von Bernd K. (prof7bit)


Lesenswert?

Sven B. schrieb:
> Das ist in dem Fall absolut kontraproduktiv.

Nein. Es ist kontraproduktiv irgendwelche internen Low-level Routinen im 
Backend vom Frontend abhängig zu machen. Sowas trennt man sauber wenns 
nicht gerade das absolut simpleste mal eben hingehackte Wegwerf-Programm 
ist. Was machst Du wenn Du diese Protokollimplementierung morgen in ner 
Konsolenanwendung brauchst? Oder für Linux mit GTK anstelle von 
Irgendwas/Qt? Oder Windows? Oder als native Library fürn Android-Handy? 
Willst Du dann das innerste nach außen stülpen nur damit die jeweilige 
GUI direkt an den Sockets herumfuhrwerken um die Arbeit zu verrichten 
die das Ding eigentlich ungefragt und klaglos eigenständig tun sollte? 
Das will kein Mensch (oder ich zumindest jedenfalls nicht, wenn Du das 
willst ist das Dein Problem).

OP hat gefragt ob er einen separaten Thread nehmen soll für die Dinge 
die das GUI nichts anzugehen haben. Die Antwort ist ein klares Ja.

von Sven B. (scummos)


Lesenswert?

Bernd K. schrieb:
> Sven B. schrieb:
>> Das ist in dem Fall absolut kontraproduktiv.
>
> Nein. Es ist kontraproduktiv irgendwelche internen Low-level Routinen im
> Backend vom Frontend abhängig zu machen.
Von welchen Low-Level-Routinen sprichst du? Qt Event Loop? Du kannst 
keine Anwendung mit Qt schreiben ohne die Event Loop mit einzubeziehen. 
Wenn deine Idee von Encapsulation ist, Netzwerkzugriff in einer 
Qt-Anwendung zu machen, indem man vermeidet die Event Loop zu benutzen, 
dann weiß ich auch nicht mehr was ich sagen soll.

> Sowas trennt man sauber wenns
> nicht gerade das absolut simpleste mal eben hingehackte Wegwerf-Programm
> ist.
Ja, klar, kein Widerspruch hier. Außer du meinst, dass man die 
Implementierung vom Netzwerk-Code vom Framework trennt das man für den 
Netzwerkzugriff verwendet, was vollkommen absurd wäre.

> Was machst Du wenn Du diese Protokollimplementierung morgen in ner
> Konsolenanwendung brauchst?
Wie gesagt, kein Widerspruch hier. Hat aber nix mit Threads zu tun.

> Oder für Linux mit GTK anstelle von
> Irgendwas/Qt?
Pech. Ungefähr genauso Pech wie wenn ich mir morgen überlege dass ich 
meine Anwendung jetzt in Haskell schreiben will und mein Netzwerk-Code 
aber schon in C ist. Du darfst hier gerne anderer Meinung sein, aber ich 
persönlich werde niemals Code in einer Anwendung schreiben mit dem 
Hintergedanken "wenn ich mal das Framework wechsle, was in jeder Zeile 
meiner Anwendung verbaut habe, möchte ich diesen Code immer noch 
verwenden können". Das ist in meiner Welt einfach grober Unfug.

> Oder Windows? Oder als native Library fürn Android-Handy?
Qt unterstützt beide Plattformen.

> OP hat gefragt ob er einen separaten Thread nehmen soll für die Dinge
> die das GUI nichts anzugehen haben. Die Antwort ist ein klares Ja.
Die Antwort ist ein klares Nein, außer die Aufgaben sind 
rechenzeitintensiv (und zwar im Sinne von "Rohdaten verarbeiten", nicht 
"Rohdaten in ein Textfeld malen", dafür bringt der Thread nämlich 
nichts) oder müssen von einer synchronen API geholt werden.

von Bernd K. (prof7bit)


Lesenswert?

Sven B. schrieb:
> Außer du meinst, dass man die
> Implementierung vom Netzwerk-Code vom Framework trennt das man für den
> Netzwerkzugriff verwendet

Nein. Ich meine daß man den Code für ein Netzwerkprotokoll nicht mit 
einem GUI-Framework implementiert. Schon gar nicht mit so einem 
Zweistelligen Multi-Magabyte-Monster wie Qt. Nicht jedes Problem ist ein 
Nagel.

von Sven B. (scummos)


Lesenswert?

Qt ist nicht nur ein GUI-Framework. QtNetwork hängt nur von QtCore ab, 
du kannst also QtNetwork verwenden ohne auch nur eine Zeile GUI-Code in 
deiner Anwendung zu haben. Nicht QtNetwork zu verwenden wenn ich eh Qt 
benutze halte ich für Schwachsinn, aber wenn dir das aufgrund 
irgendwelcher theoretischen Argumente die in der Praxis keinerlei 
Relevanz haben Spaß macht, ok.

Die GUI-Teile sind so Dinge wie QtWidgets, aber viele Komponenten von Qt 
haben mit GUI nix zu tun.

: Bearbeitet durch User
von Bernd K. (prof7bit)


Lesenswert?

Du predigst einerseits andauernd Sparsamkeit mit Einwänden über 
irgendwelche ominösen Kontextwechsel (weil Du das Wort mal irgendwo in 
nem anderen Zusammenhang aufgeschnappt hast) die bei der hier 
betrachteten Aufgabenstellkung überhaupt nicht relevant sind (weil 
nichts davon ist CPU-bound, alle beide Threads schlafen fast **immer**) 
und andererseits willst Du selbst simpleste 10-Zeiler mit ein bisschen 
leichtgewichtigem Socket-IO von Monster-Libraries wie Qt abhängig 
machen.

Ich gebs auf. EOD.

: Bearbeitet durch User
von Sven B. (scummos)


Lesenswert?

Du hast eh eine Qt-Anwendung laufen. Jetzt hast du die Wahl ob du 
einfach QtNetwork nimmst, was sich da schön einfügt, oder irgendeine 
andere Netzwerk-Bibliothek (was für deine Anwendung übrigens erstmal 
eine zusätzliche Abhängigkeit bedeutet!) und deren Event Loop (die haben 
nämlich üblicherweise alle eine) irgendwie mit der Qt Loop 
zusammenfrickelst (was überhaupt keinen Spaß macht, glaub mir). Ich 
verstehe nicht, was an der Entscheidung schwer ist.

von Bernd K. (prof7bit)


Lesenswert?

Sven B. schrieb:
> oder irgendeine
> andere Netzwerk-Bibliothek

Man braucht überhaupt keine "Netzwerk-Bibliothek" um einen socket zu 
öffnen, zu lesen, zu schreiben oder select() zu verwenden. Das Zeug ist 
alles in der libc schon drin. und in der Windows-API isses auch drin.

Gute Nacht.

von Sven B. (scummos)


Lesenswert?

Ach so, die Windows-API. Das ist natürlich harte Konkurenz in Sachen 
Entkopplung von unnötigen Dependencies.

von Bernd K. (prof7bit)


Lesenswert?

Sven B. schrieb:
> Ach so, die Windows-API. Das ist natürlich harte Konkurenz in Sachen
> Entkopplung von unnötigen Dependencies.

Nicht bei Sockets. Wie ich schrieb sind sowohl sockets als auch send(), 
recv() und select() auch in der libc und nahezu identisch in der Windows 
API. Da reicht ein einziges ifdef und weniger als eine Bildschirmseite 
Code um alle ein für allemal zu erschlagen.

von Robert L. (lrlr)


Lesenswert?

in Zeiten von, kaufe ich mir 8 oder 16 CPU Kernen:

Also ICH nehme lieber eine MEGA-ÜBER-DRÜBER Library (z.b. Indy10)


das Problem ist nämlich: wenn morgen "jemand"  (z.B. Chef) mit dem 
Falsch Fuß aufsteht, und sagt: hey, wir machen das ab jetzt mit SSL !


dann kann ich sage: jo chef, mach ma mal 2 Zeilen code mehr und des 
rennt.. ;-)



GUI in Windows funktioniert NUR mit Pollen (egal wie gern man das hat..)

in einen thread "auslagern" wird man also wohl am ehesten die 
Bearbeitung der empfangenen Daten ... (damit dem Main-Thread immer schön 
langweilig ist..)

(interessant wird das ganz eh erste wenn man einen Server hat, und 
keinen Client.. um sich dann zu überlegen wie viele Threads mach ich bei 
wievielen Verbindungen...)

von Sven B. (scummos)


Angehängte Dateien:

Lesenswert?

Bernd K. schrieb:
> Sven B. schrieb:
>> Ach so, die Windows-API. Das ist natürlich harte Konkurenz in Sachen
>> Entkopplung von unnötigen Dependencies.
>
> Nicht bei Sockets. Wie ich schrieb sind sowohl sockets als auch send(),
> recv() und select() auch in der libc und nahezu identisch in der Windows
> API. Da reicht ein einziges ifdef und weniger als eine Bildschirmseite
> Code um alle ein für allemal zu erschlagen.

Naja, ich weiß auch nicht warum's jetzt plötzlich darum geht, warum die 
Windows-API so viel toller ist um in einer Qt-Anwendung Netzwerk zu 
implementieren als QtNetwork. Mit dem eigentlichen Thema hat das alles 
nichts zu tun. Interessiert mich auch eher tangential, ich halte es für 
groben Unfug, aber wenn du willst, bitteschön. Ich benutze doch nicht Qt 
in meiner Anwendung und mache dann Netzwerk mit der Windows-API, weil 
ich da ja "nur ein #ifdef" brauche damit es nicht komplett kacke sondern 
nur ziemlich kacke ist.

Wenn Netzwerk so einfach wäre, dass man da nur "eine Bildschirmseite 
Code" braucht, gäb's dafür keine Bibliotheken wie QtNetwork und Twisted. 
Es ist halt nicht so einfach, siehe etwa das Beispiel mit SSL -- oder 
nimm an, du willst HTTP machen oder sowas, auch nicht so einfach.

Außerdem musst du dir in dem Fall deine Event Loop selber schreiben und 
wenn du dann z.B. einen Qt Slot in deinem Thread willst, wird das wieder 
anstrengend.

: Bearbeitet durch User
von Nase (Gast)


Lesenswert?

Bernd K. schrieb:
> Man braucht überhaupt keine "Netzwerk-Bibliothek" um einen socket zu
> öffnen, zu lesen, zu schreiben oder select() zu verwenden. Das Zeug ist
> alles in der libc schon drin. und in der Windows-API isses auch drin.
Ach, und ich dachte, gerade DU wolltest keine low-level-Frickelei.

Und du predigst doch auch dauernd, dass das alles nicht CPU-bound ist. 
Das spricht ja noch viel mehr dafür, es in einem Thread zu tun, weil der 
ja ohnehin fast nichts zu tun hat.
Modularisieren geht damit auch prima. Sogar noch einfacher, als wenn man 
Threads kreuz und quer miteinander synchronisieren muss.

von Bernd K. (prof7bit)


Lesenswert?

Nase schrieb:
> als wenn man
> Threads kreuz und quer miteinander synchronisieren muss.

Im vorliegenden Falle muss man gar nichts "kreuz und quer" 
synchronisieren.

Bist Du als kleines Kind mal von nem Thread gebissen worden? Oder wie 
sonst kommt diese irrationale Abneigung gegen ein x beliebiges 
Allerweltspattern zustande mit dem niemand sonst auf der Welt Probleme 
zu haben scheint? Gibts etwa noch andere grundlegende Paradigmen oder 
Sprachelemente vor denen Du so eine irrationale Angst hast? Erzähl mal!

von Sven B. (scummos)


Lesenswert?

Bernd K. schrieb:
> Oder wie
> sonst kommt diese irrationale Abneigung gegen ein x beliebiges
> Allerweltspattern zustande mit dem niemand sonst auf der Welt Probleme
> zu haben scheint?
Ich hab' mit deiner Vorgehensweise zu dem Pattern auch Probleme, damit 
sind wir immerhin schon zwei. Das ist genau wie mit diesen Design 
Patterns, die wendet man nur an wenn man einen wirklich guten Grund 
dafür hat, und nicht einfach so weil man es kann.

von Borislav B. (boris_b)


Lesenswert?

Sven B. schrieb:
> Das ist genau wie mit diesen Design
> Patterns, die wendet man nur an wenn man einen wirklich guten Grund
> dafür hat, und nicht einfach so weil man es kann.

Als Grund sollte genügen: "ich möchte eine Software schreiben".
Wenn man eine Softwarearchitektur entwirft, sollten geeignete Design 
patterns stets die Grundlage sein.

von Nase (Gast)


Lesenswert?

Boris P. schrieb:
> sollten geeignete Design
> patterns
Ja, geeignete.

Zu 'geeignet' gehört m.M.n. zum Beispiel auch, das jeweils 
einfachst-mögliche Pattern zu implementieren. Das selbst ist wieder ein 
Pattern, nämlich KISS.

Threads sind in diesem Fall ganz sicher nicht das einfachst-mögliche.

Bernd K. schrieb:
> Bist Du als kleines Kind mal von nem Thread gebissen worden?
Nö, ich für meinen Teil habe Threads verinnerlicht.

> Oder wie
> sonst kommt diese irrationale Abneigung gegen ein x beliebiges
> Allerweltspattern zustande mit dem niemand sonst auf der Welt Probleme
> zu haben scheint? Gibts etwa noch andere grundlegende Paradigmen oder
> Sprachelemente vor denen Du so eine irrationale Angst hast? Erzähl mal!
Ich habe keine Angst vor Sprachelementen im Allgemeinen. Nur gegen 
unbedachtes Einsetzen derselben.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.