Seite 1 von 1

Threads starten

Verfasst: Mittwoch 3. April 2019, 16:32
von Dan321
Hallo,

Ich habe folgendes Problem: Mein Programm ist in mehrere Klassen unterteilt und in innerhalb der Klasse soll ein Thread gestartet werden und eine Methode ausführen. Wenn ich jedoch das Programm ausführe, werden alle Threads ausgeführt. Wie kann ich das unterbinden?

Re: Threads starten

Verfasst: Mittwoch 3. April 2019, 16:35
von __deets__
In Zukunft bitte Code zeigen. Nicht alle Antworten lassen sich so einfach erraten wie diese hier.

Dein Fehler besteht darin, dass du kein callable an Thread(target=<meine-funktion>) uebergibst, sondern die Funktion gleich aufrufst. Thread(target=<meine-funktion>()). Man beachte die zuesaetzlichen Klammern. Die duerfen da nicht sein.

Re: Threads starten

Verfasst: Mittwoch 3. April 2019, 19:43
von Dan321
Danke für die Antwort, aber das ist bei mir nicht der Fall. Ich übergebe ein callable an den Thread und dennoch werden alle ausgeführt.

Re: Threads starten

Verfasst: Mittwoch 3. April 2019, 19:55
von Sirius3
@Dan321: dann fehlt immer noch eine genaue Fehlerbeschreibung und der dazu passende Code.

Re: Threads starten

Verfasst: Mittwoch 3. April 2019, 21:56
von __blackjack__
@Dan321: Ich verstehe ja die Frage schon nicht wirklich. Jede Klasse hat eine Methode die durch einen eigenen Thread ausgeführt werden soll? Klingt zumindest mal ungewöhnlich.

Re: Threads starten

Verfasst: Donnerstag 4. April 2019, 11:32
von Dan321
In jeder Klasse soll ein Thread gestartet werden, wenn die einzelnen Klassen aufgerufen werden. Doch beim Starten des Programms werden alle Threads in jeder Klasse ausgeführt. Wie kann ich die Threads nur in der Klasse ausführen?

Code: Alles auswählen

    
    def Show_frame(self, cont): 

        
        frame = self.frames[cont]
        frame.tkraise()

        
        def Signal_Handler():
            while True:
                data = s.recv(8)
                recv_function = struct.unpack('!d', data)
                function, = recv_function
                if function == 1:
                    frame = self.frames[MainMenu]
                    frame.tkraise()
                    break
                elif function == 2:
                    frame = self.frames[Timer]
                    frame.tkraise()
                    break
                elif function == 3:
                    frame = self.frames[Stopuhr]
                    frame.tkraise()
                    break
                elif function == 4:
                    frame = self.frames[Interval_Timer]
                    frame.tkraise()
                    break
                elif function == 5:
                    frame = self.frames[Score]
                    frame.tkraise()
                    break
                   

        thread_Signal_Handler = threading.Thread(target=Signal_Handler)
        thread_Signal_Handler.start()

Re: Threads starten

Verfasst: Donnerstag 4. April 2019, 12:04
von __deets__
Wenn das Ziel ist, das du GUI-Objekte veraenderst, so wie du das hier tust - dann geht das nicht mit Threads. Ja, es wirkt so als ob es geht. Aber GUIs darf man nicht aus anderen als dem Main-Thread veraendern, denn frueher oder spaeter wird das mit einem Absturz enden.

Stattdessen musst du die Reaktion auf die eingehenden Daten mit der after-Methode in tkinter realisieren. Dann kannst du komplett auf Threads verzichten.

Re: Threads starten

Verfasst: Donnerstag 4. April 2019, 12:55
von Sirius3
Du nutzt Sockets falsch. Zum ersten sollte keine Variable aus einem Buchstaben bestehen und `s` ist zudem noch global. TCP-Sockets sind Streams, das heißt, ein recv(8) kann alles zwischen einem und acht Bytes zurückliefern. Du mußt also so lange lesen, bis Du tatsächlich 8 Bytes zusammenhast.
Die Variable recv_function ist überflüssig, Du kannst diese zwei Zeilen zu einer zusammenfassen. Die if-Kaskade enthält identischen Code. Benutze ein Wörterbuch, das die Zahlen auf die Namen mapped. Es fehlt ein else-Zweig, falls etwas unbekanntes kommt, sollte das nicht einfach nur ignoriert werden. Die while-Schleife, die im Normalfall nur einmal durchlaufen wird ist aus dem selben Grund seltsam.

Lesen von Filehandles kann man statt über Threads mit tkinter auch über tkinter.createfilehandler machen. Dann läuft das innerhalb des Event-Loops und Du kannst die GUI verändern.

Bezugnehmend auf den Code, der in meinem Postfach gelandet ist:
Halte Dich an die Namenskonventionen, das macht das lesen für alle, auch für Dich, leichter: nur Klassen schreibt man mit GroßemAnfangsbuchstaben, Methoden, Funktionen und Variablen klein_mit_unterstrich, Konstanten KOMPLETT_GROSS.
Sternchenimporte vermeiden, tkinter wird üblicherweise als `import tkinter as tk` importiert und alle Namen per tk.xy angesprochen.

In `Anzeige_Timer` hast Du das selbe Problem, hier mischst Du auch verschiedene Ströme, die man nicht auseinander halten kann. Wenn Deine Uhr 5 Sekunden schickt, dann landest Du in der anderen Funktion auf der Score-Seite. Das darf nicht passieren. Du mußt die einzelnen Ströme klar trennen, z.B. mit einem Protokoll, das den Typ der Daten angibt und nur einer Schleife (tkinter.createfilehandler), die alle Events abarbeiten kann. Sagte ich schon, dass eine globale Variable `s` schlecht ist?
`struct.unpack` ist ja gerade dazu da, dass man eine ganze Struktur entpacken kann, da also drei einzelne Zahlen zu entpacken ist umständlich und unleserlich.

Code: Alles auswählen

seconds, minutes, stunden = struct.unpack('!ddd', data)
(Warum sind `stunden` deutsch benannt?)

Die Klassen `Timer`, `Stopwatch` und `Interval_Timer` sind so identisch, dass sie eigentlich nur eine Klasse sein sollten, und die Unterschiede durch Argumenten bei der Initialisierung beschrieben werden.

Re: Threads starten

Verfasst: Donnerstag 4. April 2019, 13:04
von __deets__
Ich sehe, der gute Dan321hat sich an diverse Leute gewandt, um sein Problem privat geloest zu bekommen....

Re: Threads starten

Verfasst: Donnerstag 4. April 2019, 13:16
von __deets__
@Dan321: wie waere es, wenn du mal beschreibst, welche Daten dir da genau ueber den Socket geliefert bekommst? Damit man erstmal versteht, welche Logik sich daraus ableiten muss.