Noch laufende Threads bei Prorammende?



  • Äh.. ne. Warten ? join() : detach(). Nix raten, lol.



  • Ich hab kein Wort verstanden, was willst Du mir sagen? 😉



  • Wenn noch Threads laufen, fragste den User ob er warten will (wenn die z.B. gerade eine Datei zu Ende schreiben oder so, wäre das ja blöd) oder nicht. Wenn er warten will rufst du join() auf, sonst detach().



  • Okay, verstehe, und wenn ich async/futures nutze?



  • Das ist hier nicht zu gebrauchen. Da musst du eigentlich garnichts machen, weil der Destruktor einfach so lange blockt, bis der Thread fertig ist. Insgesamt scheint mir dein threading Konzept aber etwas eigenartig, glaube das solltest du mal überdenken. Oder posten und andere das mit dem Denken probieren lassen. 😉



  • Was genau daran findest Du eigenartig? Im UI gibt es halt unterschiedliche Tabs und man kann in unterschiedlichen Tabs so diverse Berechnungen machen. Die Berechnungen können ziemlich lange dauern und hängen von Parametern ab, die der Benutzer dort eingeben kann. Er soll sie aber zur Rechenzeit ändern können, eine ständige Neuberechnung soll geschehen, solange Parameter geändert werden und der Rechenvorgang noch nicht abgeschlossen ist.

    Umgesetzt habe ich das eben dadurch, dass ich asynchrone Funktionsaufrufe nutze, die über Flags abgebrochen werden können, falls wegen Parameteränderung die Berechnung mit anderen Parametern erfolgen soll. Zu diesem Zweck starte ich dann eben einen neuen Funktionsaufruf. Warten soll der Destruktor eigentlich nicht, weil die Threads Eigentum des jeweiligen UI-Elements sind und die ja rasch zerstört werden sollen und nicht noch den Benutzer mit Warten nerven (das ist vermutlich nicht so geschickt? Soll ich einen Pool anlegen und die UI-Elemente zu den asyncs/futures mappen? Dann ist das Lebenszeitproblem des anderen Threads [also c-plusplus.net/forum-Thread] auch gelöst)

    Ideen und Kritik gerne gesehen! Das parallele Ändern von Parametern und Neuberechnen ist jedoch Voraussetzung, das habe ich als Kundenanforderung in Erfahrung gebracht.



  • Das ist nichts für Futures denke ich. Mach genau einen Thread pro Tab, der die Berechnungen durchführt. Dem gibste dann Signale. Sollte wesentlich einfacher handzuhaben sein.



  • Es gibt jedoch durchaus mehrere Berechnungen pro Tab, nicht nur eine. Genauer gesagt gibt es einige untergeordnete Rechnungen, deren Ergebnisse - wenn alle zu Ende sind - auf einer höheren Ebene wieder in eine neue Formel fließen (die aber trivial ist und daher keine asynchrone Abarbeitung braucht).

    Jedoch denke ich mittlerweile auch, dass sich Threads besser eignen. Ich könnte je Subrechnung einen Thread machen, oder? Da sich die Rechnungen auf ein UI-Element beziehen, würde ich dann gerne Besitzbeziehung UI-Element : Thread einbauen. Denkst Du, das klingt vernünftig?



  • Untergeordnete Rechnungen haben doch mit der GUI nichts zu tun. Die gehören dem Thread. Wobei hier dann auch nicht mehr wirklich die Parallelität zählt, sondern einfach das ausnutzen der Hardware. Ich würde das an deiner Stelle erstmal alles (innerhalb der Rechnung) synchron machen, denn auch wenn du hinterher umstellst, sollte das keinen Einfluss auf das Verhalten der Rechnung nach außen haben. Es ist eine Rechnung, also ein Thread. Wenn der selbst neue Threads machen will, ist das seine Sache, aber nicht Sache der GUI.



  • Die Subrechnungen werden aber von Parametern beeinflusst, die im UI eingestellt werden können. Sagen wir, es gibt 4 Parameter. Davon gehören z.B. 2 zu Rechnung 1 und 2 zu Rechnung 2. Und immer, wenn gleichzeitig Rechnung 1 und Rechnung 2 fertig sind, werden die Ergebnisse in Rechnung 3 (die von weiteren UI-Parametern abhängen) als Parameter eingehängt. Es sind also durchaus mehrere Rechnungen. Dass die Zwischenergebnisse am Ende in einer weiteren Rechnung vorkommen, ist davon ja unabhängig.

    Und auch die Ergebnisse der Subrechnungen sind für sich genommen wieder interessant und sollen so früh wie möglich dem Benutzer angezeigt werden.



  • cooky451 schrieb:

    Das ist hier nicht zu gebrauchen. Da musst du eigentlich garnichts machen, weil der Destruktor einfach so lange blockt, bis der Thread fertig ist.

    Welcher Destruktor genau? Der Dtor einer Future blockt nicht sondern lässt die Referenz auf den shared state der future einfach fallen, egal wie dessen Status ist. Futures sind gerade für asynchrone Berechnungen der sonst eher low-level Threading-Bibliothek doch deutlich vorzuziehen.



  • pumuckl schrieb:

    Welcher Destruktor genau? Der Dtor einer Future blockt nicht sondern lässt die Referenz auf den shared state der future einfach fallen, egal wie dessen Status ist. Futures sind gerade für asynchrone Berechnungen der sonst eher low-level Threading-Bibliothek doch deutlich vorzuziehen.

    Also bei mir blockt der. Siehe auch http://stackoverflow.com/questions/7620860/where-is-the-thread-going-when-a-future-leaves-scope



  • Die QT-Variante QtConcurrent::run() blockt jedenfalls auch.



  • Die Subrechnungen werden aber von Parametern beeinflusst, die im UI eingestellt werden können

    Von Parametern, nicht von GUI-Elementen. Trenne Berechnung von Darstellung! Model-View-Controller. Es scheint auch so, dass du Konzepte wie parallel-for oder Tasks etc. neu erfinden moechtest. Dafuer gibt es fertige Bibliotheken z.B. wie der Thread-Teil von C++11 wie async/future oder die PPL (Parallel Patterns Library).



  • knivil hat es ja schon gesagt: Trenne Darstellung von Bearbeitung!

    In Deinem Fall würde ich für jede gewünschte Verarbeitung ein entsprechendes Objekt erstellen und dann einem Threadpool zur nebenläufigen Verarbeitung übergeben. Ergebnisübernahme in die GUI ginge dann mit einem Future.

    QT - falls Du das, wie ich vermute, verwendest - bringt das alles schon mit.



  • Von Parametern, nicht von GUI-Elementen. Trenne Berechnung von Darstellung! Model-View-Controller.

    Ich verstehe den Einwand nicht. Im UI stellt man Parameter der Rechnung ein und die werden an die Rechnung (die natürlich getrennt woanders liegt) eingespeist. Die Ergebnisse dieser Rechnung sollen aber auch auf dem UI präsentiert werden, daher soll an das UI dann auch das Zwischenergebnis wieder mitgeteilt werden. Was wolltest Du mir jetzt genau sagen?

    [sidediscussion]
    Konsequent MVC einzuführen macht bei mir keinen Sinn. Es gibt eine sehr komplexe Rechenaufgabe, die ist auch ausgelagert. Im UI lassen sich zahlreiche Varianten aufbauen, welche die Ergebnisse der Rechenaufgabe eben mit unterschiedlichen Parametern kombinieren. Wenn ich die ganze Struktur einmal im UI und einmal noch in einem Model ablegen würde und dann auch noch die Kommunikation programmieren müsste, hätte ich fast den doppelten Aufwand. Zudem sehe ich nicht, dass ich irgendwann Mal das UI wechseln sollte. Und falls ich das doch Mal tun sollte, kann ich es immer noch auslagern. Ansätze dafür sind schon gelegt.[/sidediscussion]

    Es scheint auch so, dass du Konzepte wie parallel-for oder Tasks etc. neu erfinden moechtest. Dafuer gibt es fertige Bibliotheken wie PPL (Parallel Patterns Library).

    Das klingt sehr interessant! Ich denke jedoch, dass das meiste relativ mit Kanonen auf Spatzen geschossen ist. Die Rechnungen werden z.B. nicht weiter aufgesplittet, also nicht für sich parallelisiert. Es gibt lediglich für jede Rechnung, deren Ergebnis möglichst schnell auch auf dem Bildschirm angezeigt werden soll, einen Thread/einen asynchronen Funktionsaufruf.

    Ich habe mir jetzt so einen Threadpool gebaut, der die Aufrufe einfach sammelt und bei Erfolg dann Signale zurückschickt. Funktioniert prima und - wenn man davon absieht, dass ich vorher keinen zentralen Pool hatte und deswegen viel Gefriemel hatte - ist das eigentlich nicht Mal wirklich komplex und einfach zu nutzen. Siehst Du bei meiner allgemeinen Beschreibung einen unscharfen Mehrwert, den mir solche Bibliotheken bringen könnten?

    In Deinem Fall würde ich für jede gewünschte Verarbeitung ein entsprechendes Objekt erstellen und dann einem Threadpool zur nebenläufigen Verarbeitung übergeben. Ergebnisübernahme in die GUI ginge dann mit einem Future.

    Genau, exakt das mache ich mittlerweile auch... 🙂



  • Da sich die Rechnungen auf ein UI-Element beziehen, würde ich dann gerne Besitzbeziehung UI-Element : Thread einbauen.

    Hier wird die Trennung sehr aufgeweicht.

    Konsequent MVC einzuführen macht bei mir keinen Sinn

    Ach und ich soll raten, was bei dir Sinn macht ohne deine Architektur zu kennen. Was erwartest du als Vorschlaege, wenn sowieso alles nur allgemeines Blafasel ist. Ich weiss nur, ich haette es anders gemacht.



  • Nur die Ruhe, die eigentliche Frage des Threads ist ja eigentlich auch bereits beantwortet und ihr habt mir viele wertvolle Vorschläge gemacht. Ich weiß zwar grob, was MVC ist, verbinde damit aber stets, dass jede Firma und jedes Team das doch wieder komplett anders implementiert, darunter etwas anderes versteht und der Begriff somit für mich keine Aussagekraft hat. Außer Trennung von Frontend und Backend halt... Und deswegen habe ich auch gesagt, ich will das nicht konsequent umsetzen, weil ich da zu viel Overengineering im Gedächtnis habe, wenn Leute den Begriff benutzt haben.

    Ich denke jedenfalls, mit dem Threadpool, der Aufträge entgegennehmen kann und dem UI über Signals Ergebnisse mitteilt, habe ich die Trennung jetzt gemacht und damit ja quasi auch Deinen Vorschlag umgesetzt (außer dass ich keine Fremdbibliotheken bis auf boost/QT nutze). Danke nochmals 🙂


Anmelden zum Antworten