Threading mit Event-Steuerung

Code-Stücke können hier veröffentlicht werden.
Antworten
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Donnerstag 25. August 2005, 14:03

(Tkinter-Beispiel)

Hi!

Ich stelle es hier rein, damit es nicht verloren geht.

Dieses Beispiel demonstriert wie man ein Schleife in einem Thread mit Hilfe eines Event-Objekts anhält und wieder startet.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
"""
Threading mit Event - Beispiel
"""

import threading
import time
import Tkinter
import sys


class Motorsteuerung(threading.Thread):
    """
    Simulierte Schrittmotorsteuerung
    """
   
    def __init__(self, motormeldungen = None):
        """
        schalter = threading.Event
        motormeldungen = Rückgabe als Tkinter.StringVar, damit eine
                         Meldung in einem Label angezeigt werden kann.
        """
       
        threading.Thread.__init__(self)
       
        self.schalter = threading.Event()
        self.motormeldungen = motormeldungen
        self.canceled = False


    def run(self):
        """
        Der Motor wird initialisiert.
        Enthaelt die Steuerschleife.
        """
       
        i = 0
       
        while True:
            # Hier wird darauf gewartet, dass der Schalter
            # eingeschaltet wird.
            self.schalter.wait()
            if self.canceled:
                break
           
            # Statt einer Schrittmotor-Aansteuerung wird hier einfach
            # ein Text an die Variable "motormeldungen" uebergeben.
            # Statt mit einer Tkinter.StringVar könnte man natürlich
            # auch mit print etwas anzeigen lassen.
            i += 1
            if self.motormeldungen:
                self.motormeldungen.set("Motor laeuft (%s)" % i)
            else:
                print "Motor laeuft (%s)" % i
            time.sleep(0.5)
   
   
    def motor_start(self):
        """
        Schaltet den Motor ein
        """
        self.schalter.set()


    def motor_stopp(self):
        """
        Stoppt den Motor aus
        """
        self.schalter.clear()
   

    def motor_aus(self):
        """
        Schaltet den Motor aus
        """
        self.canceled = True
        self.schalter.set()
   

class MeinFenster(Tkinter.Tk):
    """
    GUI
    """
   
    def _center(self, *args):
        """
        Zentriert das Fenster
        """
        xpos = (self.winfo_screenwidth() - self.winfo_width()) / 2
        ypos = ((self.winfo_screenheight() - self.winfo_height()) / 2) / 100 * 90
        self.wm_geometry("+%d+%d" % (xpos,ypos))

   
    def motor_aus(self):
        """
        Schaltet die Schleife aus und schliesst das Fenster
        """
        self.motor.motor_aus()
        self.destroy()
       

    def __init__(self):
        """
        Anzeigen und initialisieren
        """
       
        # Init
        Tkinter.Tk.__init__(self)

        self.motormeldungen = Tkinter.StringVar()

        # Motor initialisieren
        self.motor = Motorsteuerung(self.motormeldungen)
        self.motor.start()

        # Fenster und Buttons
        self.config(bd = 10)
        frame = Tkinter.Frame(self)
        frame.pack()
        Tkinter.Button(
            frame,
            text = "Start",
            command = self.motor.motor_start,
            bd = 10, padx = 10, pady = 10
        ).grid(row = 0, column = 0)
        Tkinter.Button(
            frame,
            text = "Stopp",
            command = self.motor.motor_stopp,
            bd = 10, padx = 10, pady = 10
        ).grid(row = 0, column = 1)
       
        # Label
        lab = Tkinter.Label(
            self,
            text = "",
            textvariable = self.motormeldungen,
            bd = 10, padx = 10, pady = 10
        ).pack()
       
        # Aus
        Tkinter.Button(
            self,
            text = "Motor AUS",
            command = self.motor_aus,
            bd = 4
        ).pack()
       
        # Warten bis das Fenster angezeigt wird und dann zentrieren
        self.wait_visibility()
        self._center()
       

if __name__ == "__main__":
    fenster = MeinFenster()
    Tkinter.mainloop()
    sys.exit(0)
Es geht sicher besser, aber es soll ja nur als Beispiel dienen.

mfg
Gerold
:-)

Edit: Optik des Codes verbessert
Zuletzt geändert von gerold am Samstag 6. Dezember 2008, 14:49, insgesamt 2-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
bigfoot29

Donnerstag 15. Dezember 2005, 01:32

Nett :)

Gibt es eigentlich auch irgendwo ein wirklich EINFACHES Beispiel?

Ich meine, so simpel wie moeglich...

Zum Beispiel zwei Threads. Einer zaehlt alle Sekunde von 10 auf null (einen Schritt je Sekunde) und der andere zählt in .5-Sec. Schritten nach oben. Wenn Thread 1 bei Null ist, soll er Thread 2 eine Nachricht schicken, dass er sein Ergebnis ausgeben soll.

Oder gibts da irgendwo ein wirklich gutes Threading Manual? Ich kenne nur eines, und das ist leider nicht deutsch :( (und meiner nach auch fuer Threading-Einsteiger nicht allzu sehr geeignet)

Fuer jede Hilfe dankbar :)

Gruß, Bigfoot29
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Donnerstag 26. Januar 2006, 16:08

Hi!

Hier habe ich noch ein Beispiel, das zwar ohne TkInter auskommt, aber nicht unbedingt einfacher ist. Es handelt sich hier um eine kleine Gedankenspielerei, die Threads und Events erklären soll.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
"""
******************************************************************************
* Zwei Threads; Ein Thread zählt ständig nach oben, bis dieser durch ein
* Stopp-Signal (Event) aufgefordert wird, sich zu beenden. Der zweite Thread
* ist sozusagen der Timer, der von 10 bis 0 nach unten
* zählt und bei erreichen von 0 dem ersten Thread das Signal zum Beenden gibt.
* Der erste Thread erhält das Signal zum Beenden und schaltet den Hauptschalter
* aus, der sich darum gekümmert hat, dass die Hauptfunktion stehen bleibt.
******************************************************************************
"""

import time
import threading


class NachObenZaehler(threading.Thread):
    """
    Diese Klasse enthält einen Zähler, der ständig nach oben zählt und
    darauf wartet, bis er ausgeschaltet wird.
    """
   
    def __init__(self, ausschalter, hauptschalter):
        """
        Bindet den Ausschalter an eine Instanzvariable und initialisiert
        den Thread. Der Hauptschalter wird auch an eine Instanzvariable
        gebunden. Dieser hält die Hauptfunktion so lange am Leben, bis
        dieser Thread beendet wird.
        """
       
        threading.Thread.__init__(self)
       
        self.ausschalter = ausschalter
        self.hauptschalter = hauptschalter


    def run(self):
        """
        'run' ist die Methode, die aufgerufen wird, wenn 'NachObenZaehler.start()'
        ausgeführt wird.
        """
       
        i = 0
        while True:
            i += 1
           
            # Prüfen ob der Ausschalter betätigt wurde
            if self.ausschalter.isSet():
                # Der Ausschalter wurde betätigt --> Hauptschalter umlegen
                print (
                    "Erkannt, dass der Ausschalter umgelegt wurde --> "
                    "Hauptschalter umlegen"
                )
                self.hauptschalter.set()
                break
            else:
                print "NachObenZaehler: %s" % i
                time.sleep(1)


class NachUntenZaehler(threading.Thread):
    """
    Diese Klasse enthält einen Zähler, der von 10 nach 0 zählt und bei
    erreichen von 0 einen übergebenen Schalter (=threading.Event)
    einschaltet.
    """
   
    def __init__(self, ausschalter):
        """
        Bindet den Ausschalter an eine Instanzvariable und initialisiert
        den Thread
        """
       
        threading.Thread.__init__(self)

        self.ausschalter = ausschalter


    def run(self):
        """
        'run' ist die Methode, die aufgerufen wird, wenn 'NachUntenZaehler.start()'
        ausgeführt wird.
        """

        # Nach unten Zählen
        for i in range(10, 0, -1):
            print "    NachUntenZaehler: %s" % i
            time.sleep(1)
       
        # Schalter umlegen :-)
        self.ausschalter.set()
        print "    Schalter umgelegt"


def main():
    """
    Hauptprozedur: Erstellt die zwei Klasseninstanzen und startet
    danach die Threads.
    """
   
    # Hauptschalter erstellen. Dieser kümmert sich darum, dass diese
    # Funktion erst dann beendet wird, wenn der NachObenZaehler-Thread auch
    # wirklich fertig ist.
    hauptschalter = threading.Event()
   
    # Ausschalter erstellen. Dieser wird an die beiden Threads übergeben
    ausschalter = threading.Event()
   
    # Klasseninstanzen erstellen und die Schalter übergeben.
    # Die Klasseninstanz 'count_down' wird den Schalter nach Ablauf der
    # Zeit "einschalten" und damit der anderen Klasse signalisieren, dass
    # sie auslaufen soll.
    count_up = NachObenZaehler(ausschalter, hauptschalter)
    count_down = NachUntenZaehler(ausschalter)
   
    # Starten
    count_up.start()
    count_down.start()
   
    # Hier wird gewartet bis der Hauptschalter umgelegt wurde.
    hauptschalter.wait()
   
    # Meldung von der Hauptprozedur
    print "Hauptprozedur ist fertig"
   

if __name__ == "__main__":
    main()
lg
Gerold
:-)

Edit: Optik des Codes aufgebessert
Zuletzt geändert von gerold am Samstag 6. Dezember 2008, 14:50, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Bigfoot29
User
Beiträge: 7
Registriert: Donnerstag 26. Januar 2006, 10:53

Donnerstag 26. Januar 2006, 17:26

Woohoo... Danke! Bild

Exakt soetwas war gesucht. Von da an kann man das Beispiel ganz gut "umbauen"/verstehen :D

Danke, dass du dir die Arbeit gemacht hast, das zu schreiben. Bild

Ich denke, damit ist mehr Leuten geholfen als nur mir allein. :D

Gruß, Bigfoot29
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Montag 6. März 2006, 23:50

Weiter geht´s mit viel Schwung! :D Es gibt ein neues Beispiel für Threads.

Diesmal möchte ich damit die Zusammenarbeit von Threads mit Hilfe eines Queue-Objektes erklären.

Es gibt zwei Threads. Einer der Threads wartet auf Anweisungen, die von einem anderen Thread in eine Warteliste (Queue) geschrieben werden.

Dieses Szenario könnte man zum Beispiel dann einsetzen, wenn man einen Server schreiben möchte, der von anderen Programmen Anweisungen bekommt. Damit der Server nicht blockiert bis die Anweisungen abgearbeitet wurden, gibt dieser die Anweisungen in eine Warteliste (Queue). Diese Warteliste wird von einem anderen Thread unabhängig abgearbeitet. Durch die Warteliste wird garantiert, dass die Anweisungen **nacheinander** abgearbeitet werden. Das kann sehr wichtig sein, wenn man damit z.B. eine Kaffeemaschine oder einen Warenausgabeautomaten ansteuert.

Und hier das Beispiel:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import threading
import Queue
import time


class WartenderThread(threading.Thread):
    """
    Dieser Thread wartet auf die Anweisung, verschiedenste Jobs abzuarbeiten.
    """
   
    def __init__(self, jobqueue, ausschalter):
        """
        Übernimmt die Queue, die später die Jobanweisungen übergibt.
        """
       
        threading.Thread.__init__(self)
       
        self.jobqueue = jobqueue
        self.ausschalter = ausschalter
   
   
    def hallo_welt_1(self):
        """
        Diese Funktion wird aufgerufen, wenn an die
        Jobqueue "hallo_welt_1" übergeben wurde.
        """
       
        print "    Ausgefuehrt: Hallo Welt 1"


    def hallo_welt_2(self):
        """
        Diese Funktion wird aufgerufen, wenn an die
        Jobqueue "hallo_welt_2" übergeben wurde.
        """
       
        print "    Ausgefuehrt: Hallo Welt 2"


    def run(self):
        """
        'run' ist die Methode, die aufgerufen wird, wenn 'WartenderThread.start()'
        ausgeführt wird.
        """
       
        # In einer Schleife wird darauf **gewartet** bis ein neuer Job
        # an die Jobqueue übergeben wird.
        while True:
           
            # Hier wird gewartet
            anweisung = self.jobqueue.get()
           
            # Diesen Thread kurz schlafen schicken, damit wird auch die
            # Unabhängigkeit des Threades demonstriert.
            time.sleep(1)

            print "Anweisung: %s" % anweisung
           
            # Wenn Quit übergeben wurde, dann darf die Schleife
            # nicht weitergeführt werden.
            if anweisung == "quit":
                print "    Ausschalter setzen"
                self.ausschalter.set()
                break

            # Prüfen ob die Methode mit dem Namen %(anweisung)s
            # existiert. Wenn Ja, ausführen.
            if hasattr(self, anweisung):
                getattr(self, anweisung)()


class AnweisenderThread(threading.Thread):
    """
    Dieser Thread gibt Anweisungen an den anderen Thread weiter.
    """
   
    def __init__(self, jobqueue):
        """
        Übernimmt die Queue, mit der die Jobanweisungen an den anderen
        Thread übergeben werden.
        """
       
        threading.Thread.__init__(self)

        self.jobqueue = jobqueue


    def run(self):
        """
        'run' ist die Methode, die aufgerufen wird, wenn 'AnweisenderThread.start()'
        ausgeführt wird.
        """
       
        # Ein paar Anweisungen in eine Liste stecken...
        # "hallo_welt_3" ist nur ein Platzhalter, ohne zugeh. Funktion
        # im wartenden Thread.
        anweisungen = ["hallo_welt_1", "hallo_welt_2", "hallo_welt_3"]
       
        # Die ersten Anweisungen in die Queue stellen.
        for anweisung in anweisungen:
            self.jobqueue.put(anweisung)
       
        # Durch diese Wartezeit, sieht man ziemlich gut, dass der wartende
        # Thread wirklich auf die nächste Anweisung aus der Queue wartet.
        time.sleep(10)
       
        # Die nächsten zwei Anweisungen in die Queue stellen.
        for anweisung in anweisungen:
            self.jobqueue.put(anweisung)
       
        # Die Anweisung zum Beenden schicken.
        self.jobqueue.put("quit")
        return


def main():
    """
    Startet die Threads und führt den Test durch.
    """
   
    # Jobqueue erstellen (Queue)
    q = Queue.Queue()
   
    # Ausschalter erstellen (Event)
    ausschalter = threading.Event()
   
    # Threads initialisieren und dabei die Jobqueue und den
    # Ausschalter übergeben
    wt = WartenderThread(q, ausschalter)
    at = AnweisenderThread(q)
   
    # Threads starten
    wt.start() # Dieser wartet so lange bis Jobanweisungen geschickt werden.
    at.start() # Dieser schickt Jobanweisungen über die Jobqueue.
   
    # Warten bis der Ausschalter betätigt wurde. Sonst würde das
    # Programm sofort beendet werden.
    ausschalter.wait()
   
   
if __name__ == "__main__":
    main()
mfg
Gerold
:-)

Edit: "quit" wird jetzt in der Schleife geprüft und nicht mehr als Methode ausgeführt.

Edit2: Optik des Codes aufgebessert
Zuletzt geändert von gerold am Samstag 6. Dezember 2008, 14:52, insgesamt 2-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 7. März 2006, 00:26

Bei diesem Beispiel habe ich das vorherige Beispiel ein wenig abgeändert. Der Unterschied ist, dass an die Warteliste auch die Argumente für den Aufruf der Funktionen mitgegeben werden können.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import threading
import Queue
import time
import types


class WartenderThread(threading.Thread):
    """
    Dieser Thread wartet auf die Anweisung, verschiedenste Jobs abzuarbeiten.
    """
   
    def __init__(self, jobqueue, ausschalter):
        """
        Übernimmt die Queue, die später die Jobanweisungen übergibt.
        """
       
        threading.Thread.__init__(self)
       
        self.jobqueue = jobqueue
        self.ausschalter = ausschalter
   
   
    def hallo_welt_1(self):
        """
        Diese Funktion wird aufgerufen, wenn an die
        Jobqueue "hallo_welt_1" übergeben wurde.
        """
       
        print "    Ausgefuehrt: Hallo Welt 1"


    def hallo_welt_2(self, **dargs):
        """
        Diese Funktion wird aufgerufen, wenn an die
        Jobqueue "hallo_welt_2" übergeben wurde.
        """
       
        print "    Ausgefuehrt: Hallo Welt 2"
        if dargs:
            for key, value in dargs.items():
                print "        %s: %s" % (key, value)


    def run(self):
        """
        'run' ist die Methode, die aufgerufen wird, wenn 'WartenderThread.start()'
        ausgeführt wird.
        """
       
        # In einer Schleife wird darauf **gewartet** bis ein neuer Job
        # an die Jobqueue übergeben wird.
        while True:
           
            # Hier wird gewartet
            anweisung = self.jobqueue.get()
           
            # Diesen Thread kurz schlafen schicken, damit wird auch die
            # Unabhängigkeit des Threades demonstriert.
            time.sleep(1)

            print "Anweisung: %s" % str(anweisung)
           
            # Wenn die Anweisung ein Tupel oder eine Liste ist, dann
            # wird diese(r) in die Anweisung und die Argumente zerlegt.
            if isinstance(anweisung, (types.ListType, types.TupleType)):
                anweisung, dargs = anweisung
            else:
                dargs = {}

            # Wenn Quit übergeben wurde, dann darf die Schleife
            # nicht weitergeführt werden.
            if anweisung == "quit":
                print "    Ausschalter setzen"
                self.ausschalter.set()
                break

            # Prüfen ob die Methode mit dem Namen %(anweisung)s
            # existiert. Wenn Ja, ausführen.
            if hasattr(self, anweisung):
                getattr(self, anweisung)(**dargs)


class AnweisenderThread(threading.Thread):
    """
    Dieser Thread gibt Anweisungen an den anderen Thread weiter.
    """
   
    def __init__(self, jobqueue):
        """
        Übernimmt die Queue, mit der die Jobanweisungen an den anderen
        Thread übergeben werden.
        """
       
        threading.Thread.__init__(self)

        self.jobqueue = jobqueue


    def run(self):
        """
        'run' ist die Methode, die aufgerufen wird, wenn 'AnweisenderThread.start()'
        ausgeführt wird.
        """
       
        # Ein paar Anweisungen in einen Tupel stecken...
        # "hallo_welt_3" ist nur ein Platzhalter, ohne zugeh. Funktion
        # im wartenden Thread.
        anweisungen = ("hallo_welt_1", "hallo_welt_2", "hallo_welt_3")
       
        # Die ersten Anweisungen in die Queue stellen.
        for anweisung in anweisungen:
            self.jobqueue.put(anweisung)
       
        # Durch diese Wartezeit, sieht man ziemlich gut, dass der wartende
        # Thread wirklich auf die nächste Anweisung aus der Queue wartet.
        time.sleep(10)
       
        # An die Anweisung "hallo_welt_2" werden auch die Parameter
        # übergeben.
        anweisungen = (
            "hallo_welt_1",
            ("hallo_welt_2", {"vorname": "Gerold", "nachname": "Penz"}),
        )

        # Die nächsten zwei Anweisungen in die Queue stellen.
        for anweisung in anweisungen:
            self.jobqueue.put(anweisung)
       
        # Die Anweisung zum Beenden schicken.
        self.jobqueue.put("quit")
        return


def main():
    """
    Startet die Threads und führt den Test durch.
    """
   
    # Jobqueue erstellen (Queue)
    q = Queue.Queue()
   
    # Ausschalter erstellen (Event)
    ausschalter = threading.Event()
   
    # Threads initialisieren und dabei die Jobqueue und den
    # Ausschalter übergeben
    wt = WartenderThread(q, ausschalter)
    at = AnweisenderThread(q)
   
    # Threads starten
    wt.start() # Dieser wartet so lange bis Jobanweisungen geschickt werden.
    at.start() # Dieser schickt Jobanweisungen über die Jobqueue.
   
    # Warten bis der Ausschalter betätigt wurde. Sonst würde das
    # Programm sofort beendet werden.
    ausschalter.wait()
   
   
if __name__ == "__main__":
    main()
mfg
Gerold
:-)

Edit1: "quit" wird jetzt in der Schleife geprüft und nicht mehr als Methode ausgeführt.

Edit2: Optik des Codes aufgebessert
Zuletzt geändert von gerold am Samstag 6. Dezember 2008, 14:53, insgesamt 2-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Dienstag 7. März 2006, 05:24

Bitte ins WIki damit :-)
TUFKAB – the user formerly known as blackbird
Bigfoot29
User
Beiträge: 7
Registriert: Donnerstag 26. Januar 2006, 10:53

Dienstag 14. März 2006, 12:18

Großartiges Tut :) Ich bin grade dabei, das ein wenig detailierter auseinander zu nehmen, allerdings habe ich eine (kleine) Frage: Warum beendet sich dein Programm nicht von selbst? Ich bekomme die Nachricht: "Ausgefuehrt: Quit (Ausschalter gesetzt)", aber dann passiert nichts mehr. In einem Terminal bekomm ich den command prompt nicht zurueck und wenn ich das Prog mit "&" starte, dass es im Hintergrund laeuft, bekomm ich zwar mein Prompt (natuerlich) wieder, allerdings laeuft auch da im Hintergrund der Python-Prozess weiter...

Aenderungen hab ich keine vorgenommen, lediglich C&P :)
Irgendwo ein kleines Fehlerchen?

Regards, Bigfoot29
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 14. März 2006, 12:42

Bigfoot29 hat geschrieben:Irgendwo ein kleines Fehlerchen?
Hi Bigfoot29!

Danke für diesen Hinweis. Ich habe diese Skripte lediglich in meiner Entwicklungsumgebung ausprobiert. Also nicht direkt über die Kommandozeile. Da kann sich schon etwas eingeschlichen haben.

Ich werde mir die Skripte bei Zeiten noch einmal ansehen und herausfinden, wo es noch hängt.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Bigfoot29
User
Beiträge: 7
Registriert: Donnerstag 26. Januar 2006, 10:53

Dienstag 14. März 2006, 12:54

Hmmm... prompte Antwort :)

Ich hab mal mehrere "quit" Kommandos geschickt, aber irgendwie scheint der Ausschalter nicht zu funktionieren :)
Ich hab noch einen zweiten Wartenden Thread aufgemacht und noch mit einer "schlaf"-Anweisung herumgespielt... wirklich Threading :D Wenn Tread2 schlaeft/beschaeftigt ist, arbeitet Thread 1 einfach weiter. Bei 4 Quit-Anweisungen bekomme ich dann allerdings von beiden threads zweimal mitgeteilt, dass die Anweisung "self.ausschalter.set()" betaetigt worden ist. - ich vermute mal, der event kommt nicht bis zu "ausschalter.wait()" durch... :)

Aber ich -> n00b, von daher waren das nur meine Ideen. Bleibt dennoch ein großartiges Tut :)

Regards, Bigfoot29

Err... edit: Natuerlich: Danke fuer die prompte Antwort :)

Edit2: Der Schalter "ausschalter" wird gesetzt und Code nach "ausschalter.wait()" wird ausgefuehrt, wenn "quit" aufgerufen wurde, allerdings scheint das Threading-Modul das nicht allzu sehr zu beeindrucken :) koennte es sein, dass da noch die freien Threads beendet werden muessen, bevor man den main thread schliesst? selbst ein sys.exit() brachte nicht viel... *wunder*

Edit3: Koennte hieran liegen: (Python Docs)
# When the main thread exits, it is system defined whether the other threads survive. On SGI IRIX using the native thread implementation, they survive. On most other systems, they are killed without executing try ... finally clauses or executing object destructors.

# When the main thread exits, it does not do any of its usual cleanup (except that try ... finally clauses are honored), and the standard I/O files are not flushed.
Wie muesste so eine "try...finally"-Funktion aussehen? :)
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 14. März 2006, 13:26

Bigfoot29 hat geschrieben:aber irgendwie scheint der Ausschalter nicht zu funktionieren
Hi Bigfoot29!

Ich habe die Beispiele ausgebessert. Der Fehler war, dass ich den Thread trotz der "Quit"-Anweisung noch an der Queue horchen lies. Da bleibt der Thread so lange stehen, bis die nächste Anweisung über die Queue kommt.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Bigfoot29
User
Beiträge: 7
Registriert: Donnerstag 26. Januar 2006, 10:53

Dienstag 14. März 2006, 13:32

mKay, das wars :) Jetzt funktioniert alles...

Zeit, die Weltherrschaft an mich zu reissen!
... äh, hab ich das jetzt wirklich laut gesagt? :shock:

Wie schon gesagt: Herzlichen Dank!

Regards, Bigfoot29
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 15. März 2006, 17:23

blackbird hat geschrieben:Bitte ins WIki damit :-)
Hab ich gemacht: http://wiki.python.de/Threading_Beispiel1 Aber leider ohne viel Informationen... Bitte ergänzen :lol:

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten