Thread per Buttonclick beenden

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
dirty sanchez
User
Beiträge: 42
Registriert: Freitag 27. Juni 2008, 12:21

Hallo,

ich benutze das Modaul threading. Wie kann man einen schlafenden Thread per Button-Click beenden?
BlackJack

Threads kann man von "aussen" nicht beenden. Üblicherweise spendiert man Threads deshalb ein Flag, welches innerhalb des Threads regelmässig überprüft wird.
dirty sanchez
User
Beiträge: 42
Registriert: Freitag 27. Juni 2008, 12:21

ok danke, aber das hab ich schonmal so gelesen, jedoch dieses flag kann ja während im thread ein sleep(...) aktiv ist auch nicht überprüft werden, richtig? genau das ist mein problem! gibts wohl keine Lösung?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Doch, indem du den Flag in der Hauptschleife des Threads überprüfst. Dort sollte irgendwo ein Lock/eine Queue sein, welche immer dann gelöst wird, wenn eine Aktion im Thread ausgeführt werden soll. Als Aktion könntest du von außen dann "Beenden" aufrufen und der Lock wird überprüft.

Was genau hast du denn mit dem "sleep" vor, in Threads kommt man eigentlich immer ohne aus. Zur Not kannst du das Sleep mit dem Flag verbinden, so dass bei einem abgebrochenen sleep der Thread verlassen wird.
dirty sanchez
User
Beiträge: 42
Registriert: Freitag 27. Juni 2008, 12:21

ich hab ne Liste von Videos, diese will ich nacheinander jedoch nicht in einer playlist sondern einzeln abspielen. abhängig von der dauer des laufenden videos schläft der thread nachdem er das video gestartet hat. ist die zeit abgelaufen wacht der thread auf und startet das nächste video. jetzt brauch ich eben noch eine möglichkeit das ganze szenario mit einem button zu beenden. weiß halt nicht genau wie ich das mache. der button muss den thread ja immer beenden können egal wo ich mich in meiner schleife im thread befinde!?
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

mach eben viele kleine sleeps.

Code: Alles auswählen

def littlesleep(seconds, step=0.5):
    div, r = divmod(seconds, step)
    div += bool(r)
    for _ in xrange(int(div)):
        sleep(step)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Dann bietet sich ein Lock mit angegebenem Timeout geradezu als Lösung an.
dirty sanchez
User
Beiträge: 42
Registriert: Freitag 27. Juni 2008, 12:21

danke aber versteh nicht ganz was das bringt. also wie kann ich das flag abfragen? hab doch eigentlich ne while schleife um das ganze gebilde drumherum und dann ist doch egal ob ich
z.b. sleep(35) oder
for i in range(35):
sleep(1)
schreibe. hab irgendwie bei beiden varianten kein erfolg!?
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Code: Alles auswählen

from __future__ import division
from time import sleep


def littlesleep(seconds, step=0.5):
    div, r = divmod(seconds, step)
    div += bool(r)
    for _ in xrange(int(div)):
        yield sleep(step)

if __name__ == '__main__':
    sleeper = littlesleep(5)
    breaker = False
    for _ in sleeper:
        if breaker:
            break
So. Das wirst du ja wohl noch selbst auf deinen Code übertragen können, oder?
dirty sanchez
User
Beiträge: 42
Registriert: Freitag 27. Juni 2008, 12:21

mir fehlt hier noch irgendwie der zusammenhang zu threading!?
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

wenn ich das ganze nen Thread einbaue der sich nach Zeit x beendet sagst du bestimmt, dass du dann den Zusammenhang mit dem Knopfdruck nicht siehst..

Irgendwie musst du auch mal selbst anfangen.

Aber bitteschön:

Code: Alles auswählen

from __future__ import division
from time import sleep, time
import threading

class Sleeper(threading.Thread):

    def __init__(self, sleeptime, step=0.5):
        self.sleeptime = sleeptime
        self.step = step
        threading.Thread.__init__(self)

    def run(self):
        self.exit = False
        sleeper = littlesleep(5)
        for _ in sleeper:
            if self.exit:
                break
    



def littlesleep(seconds, step=0.5):
    div, r = divmod(seconds, step)
    div += bool(r)
    for _ in xrange(int(div)):
        yield sleep(step)

if __name__ == '__main__':
    start =  time()
    t = Sleeper(10)
    t.start()
    sleep(1)
    print time() - start
    t.exit = True
    print time () - start
   
dirty sanchez
User
Beiträge: 42
Registriert: Freitag 27. Juni 2008, 12:21

danke für deine hilfe und sorry dass ich mich so blöd dranstelle. ich versuch mein problem zu schildern:

Code: Alles auswählen

self.connect(self.button1, QtCore.SIGNAL("clicked()"), self.abspielen)
self.connect(self.button2, QtCore.SIGNAL("clicked()"), self.beenden)

def abspielen(self):
        threadobject = threads()
        threadobject.start()

def starten(self, video):
        arg = [pfad]
        process = subprocess.Popen(arg)

def beenden(self):
        threadobject = threads()
        threadobject.stop()

class threads(Thread, hauptklasse):
    def __init__(self):
        Thread.__init__(self)
        self.stopped = Event()

    def run(self):
        print self.stopped.isSet()
        while not self.stopped.isSet():
            for Element in liste:
                self.starten(Element)
                print 'Video wird abgespielt'
                sleep(Element.dauer)
                print 'Thread aufgewacht!'
            print 'Letztes Video abgespielt!'
            self.beenden()
        self.beenden()

    def stop(self):
        #Anhalten ausloesen
        self.stopped.set()
das stoppen funktioniert nicht. obwohl mein event ausgelöst wird und self.stopped = True ist. nachdem der thread aufgewacht ist ist self.stopped wieder False , ka warum. hoffe das hilft weiter um mir weiterzuhelfen.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Ich seh schon, du hast meinen Code nicht ernsthaft angeschaut...

Das littlesleep schrieb ich nicht ohne Grund...argh.
dirty sanchez
User
Beiträge: 42
Registriert: Freitag 27. Juni 2008, 12:21

tut mir leid konnte deinen code nicht so ganz auf mein problem beziehen. liegt das problem also am sleep? normal müsste doch dann spätestens nach dem sleep der thread beendet werden oder?
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

probiers doch erstmal ohne Gui.

Teste an meinem Beispiel rum und teste als Vergleich dazu nen Thread, der anstatt des `for _ in littlesleep(n)` nen normales sleep(n) benutzt.

Und poste bitte Code, der für sich stehend ausführbar ist und dein Problem zeigt.
dirty sanchez
User
Beiträge: 42
Registriert: Freitag 27. Juni 2008, 12:21

Code: Alles auswählen

import threading

class MyThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
       
        self.stopped = threading.Event()
   
    def run(self):
        while not self.stopped.isSet():
            #Hier irgend etwas machen
            ....
   
    def stop(self):
        #Anhalten ausloesen
        self.stopped.set() 
das hat EyDu bei nem älteren Beitrag "Thread zerstören" geschrieben. ich versteh nicht ganz warum bei dem event ein self davor muss. dann würd mich noch interessieren wie man die funktion stop von einer anderen klasse aus aufrufen kann!? vllt kann jemand helfe?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

dirty sanchez hat geschrieben:das hat EyDu bei nem älteren Beitrag "Thread zerstören" geschrieben. ich versteh nicht ganz warum bei dem event ein self davor muss. dann würd mich noch interessieren wie man die funktion stop von einer anderen klasse aus aufrufen kann!? vllt kann jemand helfe?
Ein Tutorial kann helfen, denn das ist, ganz ehrlich, OOP-Grundwissen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
dirty sanchez
User
Beiträge: 42
Registriert: Freitag 27. Juni 2008, 12:21

naja ein tutorial kann meine frage nicht beantworten. ich weiß auch dass ich die funktion stop in einer anderen klasse so aufrufen kann:

Code: Alles auswählen

t = MyThread()
t.stop()
aber es funktioniert irgendwie nicht. das event wird auch von false auf true gesetzt, jedoch mein thread wird nicht beendet!?
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

dirty sanchez hat geschrieben:naja ein tutorial kann meine frage nicht beantworten. ich weiß auch dass ich die funktion stop in einer anderen klasse so aufrufen kann:[...]
Du hast völlig recht. Man ein Tutorial auch nicht ordentlich durcharbeitet, dann beantwortest es gar keine Fragen.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Wenn es das stopped-Flag setzt, musst du natürlich warten, bis run() wieder die Abbruchbedingung prüft. Das scheint bei dir nicht der Fall zu sein.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten