Seite 1 von 2

Thread per Buttonclick beenden

Verfasst: Montag 28. Juli 2008, 14:12
von dirty sanchez
Hallo,

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

Verfasst: Montag 28. Juli 2008, 19:19
von BlackJack
Threads kann man von "aussen" nicht beenden. Üblicherweise spendiert man Threads deshalb ein Flag, welches innerhalb des Threads regelmässig überprüft wird.

Verfasst: Dienstag 29. Juli 2008, 07:31
von dirty sanchez
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?

Verfasst: Dienstag 29. Juli 2008, 08:30
von EyDu
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.

Verfasst: Dienstag 29. Juli 2008, 08:42
von dirty sanchez
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!?

Verfasst: Dienstag 29. Juli 2008, 08:52
von audax
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)

Verfasst: Dienstag 29. Juli 2008, 09:21
von EyDu
Dann bietet sich ein Lock mit angegebenem Timeout geradezu als Lösung an.

Verfasst: Dienstag 29. Juli 2008, 09:22
von dirty sanchez
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!?

Verfasst: Dienstag 29. Juli 2008, 11:09
von audax

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?

Verfasst: Dienstag 29. Juli 2008, 13:02
von dirty sanchez
mir fehlt hier noch irgendwie der zusammenhang zu threading!?

Verfasst: Dienstag 29. Juli 2008, 13:25
von audax
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
   

Verfasst: Dienstag 29. Juli 2008, 14:33
von dirty sanchez
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.

Verfasst: Dienstag 29. Juli 2008, 14:35
von audax
Ich seh schon, du hast meinen Code nicht ernsthaft angeschaut...

Das littlesleep schrieb ich nicht ohne Grund...argh.

Verfasst: Dienstag 29. Juli 2008, 14:41
von dirty sanchez
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?

Verfasst: Dienstag 29. Juli 2008, 15:00
von audax
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.

Verfasst: Freitag 1. August 2008, 11:01
von dirty sanchez

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?

Verfasst: Freitag 1. August 2008, 11:51
von Leonidas
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.

Verfasst: Freitag 1. August 2008, 12:14
von dirty sanchez
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!?

Verfasst: Freitag 1. August 2008, 12:16
von audax
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.

Verfasst: Freitag 1. August 2008, 12:18
von Leonidas
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.