Erforderliche Benutzereingaben legt den Rechner lahm

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
DerLichtMensch
User
Beiträge: 6
Registriert: Freitag 8. Januar 2010, 15:57

Hallo,

ich habe folgendes Problem: Ich habe Routinen die Im Thread ablaufen, ist innerhalb dieser Routine eine Benutzereingabe notwendig, geht meine CPU Auslastung auf 100%, tätige ich die Eingabe, läuft der Rechner wieder normal.

Meine Vermutung ist, das zu oft die Eingabe durch den Benutzer abgefragt wird.

Nun meine Frage gibt es eine Möglichkeit, dies zu lösen?

Benutze python 24 und wx.python.

Danke und ein schönes Wochenende.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Ohne den passenden Code wird das kaum zu beantworten sein.
Was nicht gut klingt ist die Kombination "Thread und GUI" - hängt aber letztlich davon ab, was du genau gemacht hast.
Benutzeravatar
Masaru
User
Beiträge: 425
Registriert: Mittwoch 4. August 2004, 22:17

Mhm, die Frage ist eindeutig was für das wxPythonSubforum ... und erfordert wie numerix bereits sagte, wenigstens ein paar Zeilen Code.
DerLichtMensch
User
Beiträge: 6
Registriert: Freitag 8. Januar 2010, 15:57

Der Tread

Code: Alles auswählen

class worker_thread(threading.Thread, object):
    """!@brief Klasse, die die eigentliche Arbeitsroutine in einem separaten Thread
        ausführt, damit die GUI bedienbar bleibt (für wxPython so erforderlich).
        
        Neben dem eigentlichen Ausführen der Funktion in einem Thread werden
        auch alle der Funktion übergebenen graphischen Elemente umgeleitet
        und threadkonform verarbeitet, also mit wx.CallAfter()."""
    
    def __init__(self, function, caller, finalEvent=None):
        """!@brief Konstruktor
            @param[in] self Instanz dieser Klasse
            @param[in] function Die auszuführende Funktion
            @param[in] caller Struktur mit den betroffenen Klassen und Funktionen
            @param[in] finalEvent hier kann eine Methode übergeben werden, welche
                       nach Ablauf der eigentlichen Funktion aufgerufen wird.
                       Typisches Beispiel: update_gui() muss am Ende des Threads
                       aufgerufen werden, dies darf aber nicht aus dem Thread
                       heraus geschehen"""
        # Basisklasse initialisieren
        threading.Thread.__init__(self)
        
        ## Die im Thread auszuführende Funktion
        self.function = function
        
        ## @brief Struktur die der im Thread laufenden Funktion übergeben wird
        ##
        ## Darin enthalten sind Funktionen und Klassen mit Daten. Die Funktionen
        ## müssen noch threadsicher umgeleitet werden!
        self.caller = caller
        
        ## Event, welches am Ende der run-Methode ausgelöst wird
        self.finalEvent = finalEvent
        
        # Alle GUI Funktionen auf den ThreadWrapper umleiten
        self.caller.gui.redirect_all(mvpc_lib.ThreadWrapper)
        
        # Den Task starten. Dieser Aufruf kehrt sofort zurück, da der Task ja
        # parallel läuft. Der Task endet automatisch, wenn die oben übergebene
        # Funktion zurückkehrt.
        # self.start() ist in threading.Thread definiert und ruft automatisch
        # die weiter unten zu findende Methode run() auf.
        self.start()
    
    def run(self):
        """!@brief Beim Start des Thread die übergebene Funktion mit den übergebenen
            Parametern (caller) starten
            @param[in] self Instanz dieser Klasse"""
        # Der Task endet nach der Rückkehr aus self.function() automatisch,
        # es sind keine weiteren Aktionen dafür notwendig!
        self.function(self.caller)
        
        # Die GUI-Funktionen wieder restaurieren. Das ist notwendig, da
        # sie per Referenz übergeben und verändert wurden!!!
        self.caller.gui.direct()
        
        # Event an Methode knüpfen, welche nach Abschluss des Threads aufgerufen wird.
        # Bei jeder Instanz wird dieses Event neu gekoppelt. Ansonsten müsste man das
        # Event vor dem Threadstart von Hand setzen und nach Threadende wieder zurück-
        # setzen. Die hätte den Nachteil, dass bei einem abgebrochenen Thread niemals
        # der Fall "nach Threadende" erreicht wird und somit nicht zurückgesetzt wird.
        # Das Koppeln findet in der run-Methode statt, weil sich sonst 2 gleichzeitig
        # laufende worker_threads gegenseitig behindern könnten.
        EVT_THREAD_DONE(working_area, self.finalEvent)
        
        # Event auslösen, wenn die run-Methode zum Ende kommt
        # Dies ist sinnvoll, weil man den Thread nicht mit join() beobachten kann.
        # Somit kann man vor dem Aufrufen des Threads eine Methode bestimmen, welche
        # nach Ablauf ausgeführt werden soll. Das bringt dann das selbe Ergebnis, wie
        # ein Warten per join().
        wx.PostEvent(working_area, WorkerThreadDoneEvent())]
[/code]

Wenn ein Button kommt

Code: Alles auswählen

class ButtonClass:
    """!@brief Struktur, die Rückgabewerte für Buttons verwaltet"""
    
    def __init__(self, text, buttonType, argument):
        """!@brief Konstruktor
            @param[in] self Die Instanz der Klasse
            @param[in] text Der Text auf dem Button
            @param[in] buttonType Wert aus const.button_*
            @param[in] argument notwendige Argumente für die jeweilige Aktion
                                Je nach Typ unterschiedlich. Beispiel: für
                                button_execute muss die Kommandozeile, die
                                ausgeführt werden soll angegeben werden"""
        if isinstance(text, basestring):
            ## Der Wert
            self.text = text
            
            ## Typ
            self.type = buttonType
            
            ## das Argument
            self.arg = argument
        else:
            raise _("Wrong Input")
    
    def performAction(self, event):
        """!@brief Event, welcher beim Klick auf den Button ausgeführt wird
            @param[in] self Die Instanz der Klasse
            @param[in] event das Event"""
        
        if self.type == const.button_execute:
            # Als Argument muss bei dieser Aktion der aufzurufende Befehl als
            # String übergeben werden
            
            # direkt Starten geht nicht, dies muss in einem Thread geschehen,
            # weil os.system() blockiert, bis der Befehl abgearbeitet ist
            # Abgearbeitet ist dann, wenn das aufgerufene Programm beendet wird
            # und den ReturnCode liefert
            thread = redirection_thread(os.system, '"%s"' % self.arg)
            thread.filename = self.arg
            thread.start()
            childAppThreads.append(thread)
DerLichtMensch
User
Beiträge: 6
Registriert: Freitag 8. Januar 2010, 15:57

Habe das Problem gefunden es gab eine Schleife in der nix gemacht wurde. Einen time.sleep eingebaut alles gut.

def ThreadWrapper(function, *argp, **argk):

def __handle(worker_var, function, *argp, **argk):
answer = [False, None]
wx.CallAfter(__handle, answer, function, *argp, **argk)
while answer[0] == False:
time.sleep(0.01)
return answer[1]
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Wie schön, dass du gerade dieses Codestück unterschlagen hattest.
DerLichtMensch
User
Beiträge: 6
Registriert: Freitag 8. Januar 2010, 15:57

Ja als ich den Fehler gefunden habe, habe ich es auch gemerkt, das Progrmm wird halt langsam echt groß.
Antworten