Thread stürzt ab

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.
Antworten
Benutzeravatar
The Honk
User
Beiträge: 15
Registriert: Montag 22. September 2008, 15:38

Hi,
da meine threads immer gerne mal ohne offensichtlichen Grund abstürzen hab ich mir ein Testprogramm mit nur einem Thread geschrieben, um zu verstehen was ich falsch mache. Auch mit dem Programm ist mir leider nicht klargeworden, warum das Programm abstürzt.

Es soll ein Bild beim Drücken der rechten Pfeiltase nach rechts bewegen:

Code: Alles auswählen

import Image
import Tkinter
import Canvas
import time
from threading import *
from ImageTk import *

class Raumschiff(Thread):
    def __init__(self,armor,maxhealth,speed,imagepfad):
        Thread.__init__(self)
        self.image=PhotoImage(Image.open(imagepfad))
        self.movement=Event()
        #self.lockment=Lock()
        self.x=100
        self.y=200

    def erscheine(self,master,x,y):
        self.frame=Tkinter.Frame(master,bg="green",height="40",width="100")
        self.frame.place(x=self.x,y=self.y)
        self.canvas=Tkinter.Canvas(self.frame,height="40",width="100", bg="red")
        self.canvas.pack()
        self.c_image=self.canvas.create_image(x,y,image=self.image)
        print self.c_image

    def move(self,event):
        print "move"
        self.movement.set()

    def stopmoving(self,event):
        print "stopmove"
        self.movement.clear()

    def run(self):
        count=1
        while 1:
            #self.lockment.acquire()
            self.movement.wait()
            print count," run ",self.x,self.y
            self.x+=1
            self.frame.place(x=self.x,y=self.y)
            count+=1
            time.sleep(0.1)
            #self.lockment.release()

class Gui:
    def __init__(self):
        self.fenster=Tkinter.Tk()
        self.fenster.geometry("800x600")
        self.canvas=Tkinter.Canvas(self.fenster,height="600",width="800", bg="black")
        self.canvas.pack()

        self.test_raumschiff=Raumschiff(10,100,20,"Bilder/test.bmp")
        self.test_raumschiff.erscheine(self.fenster,100,200)
        self.test_raumschiff.start()

        self.fenster.bind("<KeyPress-Right>",self.test_raumschiff.move)
        self.fenster.bind("<KeyRelease-Right>",self.test_raumschiff.stopmoving)

        
my_gui=Gui()
print "ENDE"
Danke für eure Hilfe.
Dem Weisen gilt Schweigen als Antwort
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Tkinter ist nicht threadsafe, d.h. sämtliche Gui-Aktionen müssen in Main-Thread geschehen.
Benutzeravatar
The Honk
User
Beiträge: 15
Registriert: Montag 22. September 2008, 15:38

wie definiere ich den MainThread?
Dem Weisen gilt Schweigen als Antwort
lunar

Den definierst du nicht, der ist einfach da. Das ist der Thread, in dem die GUI erzeugt wurde.

Aus allen anderen Threads kann kein Zugriff auf die GUI erfolgen.
BlackJack

Gar nicht, das ist der, der schon läuft, ohne dass Du selber welche startest. Auf die GUI darfst Du nur aus dem Thread zugreifen, in dem die `mainloop()` aufgerufen wird.
Benutzeravatar
The Honk
User
Beiträge: 15
Registriert: Montag 22. September 2008, 15:38

Danke.
Kann man das mit dem Threadsave ändern bzw. hat das schon mal irgendjmd gemacht?
Dem Weisen gilt Schweigen als Antwort
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

The Honk hat geschrieben:Kann man das mit dem Threadsave ändern bzw. hat das schon mal irgendjmd gemacht?
Um Tkinter threadsafe zu machen müsstest du die ganze Library umschreiben, noch dazu dass ich vermute das Tk genausowenig threadsafe ist wohl auch Tk umstrukturieren. Eigentlich ist keine der großen GUI-Libraries threadsafe.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
name
User
Beiträge: 254
Registriert: Dienstag 5. September 2006, 16:35
Wohnort: Wien
Kontaktdaten:

Leonidas hat geschrieben:
The Honk hat geschrieben:Kann man das mit dem Threadsave ändern bzw. hat das schon mal irgendjmd gemacht?
Um Tkinter threadsafe zu machen müsstest du die ganze Library umschreiben, noch dazu dass ich vermute das Tk genausowenig threadsafe ist wohl auch Tk umstrukturieren. Eigentlich ist keine der großen GUI-Libraries threadsafe.
Jain, wx haette sein "wx.CallAfter", das das schoen umgeht, die nicht Thread-Safety.
Ohloh | Mein Blog | Jabber: segfaulthunter@swissjabber.eu | asynchia – asynchrone Netzwerkbibliothek

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.
lunar

Man kann das Programm allerdings so umschreiben, dass der Arbeitsthread mit dem Hauptthread kommuniziert, und alle GUI-Zugriffe im Hauptthread erfolgen.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

name hat geschrieben:Jain, wx haette sein "wx.CallAfter", das das schoen umgeht, die nicht Thread-Safety.
Jedes Toolkit hat da Möglichkeiten Gleichzeitigkeit ohne Thread-Probleme zu lösen, aber das war ja nicht gefragt. ich hätte natürlich noch erwähnen müssen, dass man ein Toolkit nicht threadsafe bekommen muss, um mit mehreren Threads zu arbeiten, aber das haben andere ja inzwischen gesagt.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
lunar

name hat geschrieben:
Leonidas hat geschrieben:
The Honk hat geschrieben:Kann man das mit dem Threadsave ändern bzw. hat das schon mal irgendjmd gemacht?
Um Tkinter threadsafe zu machen müsstest du die ganze Library umschreiben, noch dazu dass ich vermute das Tk genausowenig threadsafe ist wohl auch Tk umstrukturieren. Eigentlich ist keine der großen GUI-Libraries threadsafe.
Jain, wx haette sein "wx.CallAfter", das das schoen umgeht, die nicht Thread-Safety.
Das macht wx trotzdem noch nicht threadsicher. Wx hat nur – genau wie Qt und wahrscheinlich auch Gtk – nur Tools, welche die Kommunikation über verschiedene Threads hinweg erleichtern. Tk fehlt das eben, was aber nichts daran ändert, dass weder Tk noch Qt, Gtk oder Wx thread-sicher sind. Was wahrscheinlich technisch auch gar nicht möglich ist, da Zeichenoperationen eines GUI-Clients halt in gewisser Weise atomar sein müssen.
BlackJack

Was fehlt `Tk` da? Es gibt eine `after()`-Methode auf Widgets.
lunar

BlackJack hat geschrieben:Was fehlt `Tk` da? Es gibt eine `after()`-Methode auf Widgets.
Das wusste ich nicht. Ich habe mit Tk nichts am Hut. Auf das Fehlen solcher Möglichkeiten habe ich einfach nur geschlossen, weil das hier niemand vorgeschlagen hat.
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Ob es lohnenswert wäre, eine Wiki-Seite dafür anzulegen? Weil irgendwie kommt die Frage doch desöfteren auf.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Trundle hat geschrieben:Ob es lohnenswert wäre, eine Wiki-Seite dafür anzulegen?
Zu was? Aber generell: es lohnt sich fast immer, daher ermutige ich auch Leute Sachen die nicht offensichtlich sind ins Wiki zu schreiben. Am besten entweder direkt in die FAQ oder die neue Seite in den FAQ verlinken.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Dazu, dass die gängigen Toolkits nicht thread-sicher sind und wie man trotzdem Threads benutzen kann, also was es zu beachten gilt, welche Funktionen/Möglichkeiten die einzelnen Toolkits zur Verfügung stellen etc. pp.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
Antworten