Verständnissproblem bei Threads in wxpython

Plattformunabhängige GUIs mit wxWidgets.
Antworten
copyy
User
Beiträge: 4
Registriert: Sonntag 26. April 2009, 15:29

Sonntag 26. April 2009, 17:26

Hallo,
ich versuche eine GUI zu programieren bei der im Hintergrund rechenintensive Operationen ausgeführt werden. Aber obwohl ich diese in einem eigenem Thread starte reagiert die Oberfläsche erst wieder wenn die Operationen ausgeführt wurden.

In einem kleinen Testprogramm tritt das Problem auch schon auf:

Code: Alles auswählen

# -*- coding: utf-8 -*-

import wx
import thread
import time



def rechnen(x):
    print len(str(2**x))
    
def warten(x):
    time.sleep(x)
    print "rdy"


class Frame(wx.Frame):
    def __init__(self,parent):
        wx.Frame.__init__(self,parent)
        
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        btn = wx.Button(self,label = "rechen")
        btn.Bind(wx.EVT_BUTTON,self.onBtn1)
        
        btn2 = wx.Button(self,label = "warten")
        btn2.Bind(wx.EVT_BUTTON,self.onBtn2)
        
        btn3 = wx.Button(self, label = "sofort")
        btn3.Bind(wx.EVT_BUTTON,self.onBtn3)
        
        sizer.Add(btn)
        sizer.Add(btn2)
        sizer.Add(btn3)
        
        
        self.SetSizer(sizer)
        
    def onBtn1(self,event):
        thread.start_new(rechnen, (200000,))
        print "btn1"
        
    def onBtn2(self,event):
        thread.start_new(warten, (5,))
        print "btn2"
        
    def onBtn3(self,event):
        print "hallo"
        
        
        

def main():

    app = wx.PySimpleApp(0)
    frame = Frame(None)
    frame.Show()
    app.MainLoop()

if __name__ == "__main__":
    main()
Verhalten soll sich mein Programm wie die Funktion hinter dem Warten-Button, ein Thread wird gestarted, es wird z.b. auf Druck auf Sofort reagiert und es erscheint als Ausgabe btn2, hallo, rdy.
Mein Programm verhält sich aber wie die Funktion hinter dem Rechnen-Button. Bei Druck auf den Button und sofort danach auf den Sofort-Button erscheint nicht btn1,hallo,zahl wie ich es erwarten würde sondern btn1,zahl,hallo.

Wo liegt mien Fehler? Wieso warted die GUI auf die Berechnungen von der rechen-Funktion obwohl diese doch nebenbei in einem neuen Thread laufen soll?

Ich benutze Windows XP und Python 2.5

Mit Freundlichen Grüßen
copyy
DasIch
User
Beiträge: 2450
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Sonntag 26. April 2009, 23:43

Das thread Modul ist ziemlich low-level und sollte man deswegen nicht unbedingt verwenden; in Python 3 ist dies auch mit einem Unterstrich geprefixt.

Verwende stattdessen das threading Modul.

Code: Alles auswählen

from threading import Thread
from time import sleep
thread = Thread(target=sleep, args=(10, ))
thread.start()
Es gibt natürlich auch ein kwargs Argument für dass man ein dict übergeben kann.
copyy
User
Beiträge: 4
Registriert: Sonntag 26. April 2009, 15:29

Montag 27. April 2009, 08:53

Hallo DasIch,

danke für deine Antwort, aber leider hängt meine Oberfläche auch wenn ich das threading-Modul verwende.
Sobald die zeitintensive Funktion gestartet wird bleibt der Hauptthread komplett stehen und reagiert erst wieder wenn der zeitintensive Thread abgeschlossen ist.

Mit Freundlichen Grüßen
copyy
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Montag 27. April 2009, 13:15

Wahrscheinlich liegt das am GIL. Probier doch mal

Code: Alles auswählen

def rechnen(x):
    t = 1
    for _ in xrange(x):
        t *= 2
    print len(str(t))
MfG
HWK
copyy
User
Beiträge: 4
Registriert: Sonntag 26. April 2009, 15:29

Montag 27. April 2009, 15:22

Vielen Dank HWK,

das scheint mein Problem zu sein.
In meinem Programm werden die zeitintensieven Berechungng in einem in C programierten Modul durchgeführt das wohl durch einen GIL die Oberfläche lahm legt.

Gibt es denn eine Möglichkeit herauszufinden ob ein GIL aufgerufen wurde bzw zu verhindern das ein GIL in der C-Extention aufgerufen wird?

Mit Freundlichen Grüßen
copyy
copyy
User
Beiträge: 4
Registriert: Sonntag 26. April 2009, 15:29

Montag 27. April 2009, 22:03

ich glaube ich habe mein Problem gelöst.
mit
Py_BEGIN_ALLOW_THREADS
und
Py_END_ALLOW_THREADS
in meiner c-Extention um die Berechnungen herum scheine ich ein global interpreter lock zu umgehen und alles läuft schön parallel.

nochmals vielen Dank HWK für den Tipp mit dem GIL

Mit Freundlichen Grüßen
copyy
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Dienstag 28. April 2009, 11:35

Schön, dass Du Dir selbst helfen konntest.
MfG
HWK
Antworten