Seite 1 von 1

Fortlaufen eines Programms???

Verfasst: Mittwoch 24. Dezember 2008, 10:35
von meister56
Ich versuche gerade Tetris in python zu programmieren und es ist mir auch schon fast alles gelungen, doch bei mir ist ein Problem aufgetaucht!
Ich weis nicht wie ich die Anweisung geben kann das pro eine bestimmte Zeit etwas geschehen soll (hier das runterbewegen der Figuren)
Kann mir jem. raueshelfen? :?: [/code]

Verfasst: Mittwoch 24. Dezember 2008, 10:45
von Birne94
ein zeitgesteuerter thread?

Code: Alles auswählen

import threading, time

class T (threading.Thread):
    def run(self):
        while 1:
            mache_etwas()
            time.sleep(0.1)
Diese Klasse ruft dann alle Zentelsekunde die Funktion mache_etwas auf.

Start der Schleife:

Code: Alles auswählen

t = T()
t.start()
Ich hoffe, dass ich dich richtig verstanden habe :D

Verfasst: Mittwoch 24. Dezember 2008, 11:17
von meister56
so ehnlich habe ich es versucht, das problem dabei war das es durch das "time.sleep" das ganze program net mehr lief( du konntest dann gar keine zusäzlichen Buttons wie z.B. "Pause" drücken)!

Verfasst: Mittwoch 24. Dezember 2008, 11:23
von Birne94

Code: Alles auswählen

import threading, time

class T (threading.Thread):
    def __init__(self):
        threading.__init__(self)
        self._paused = 0
    def run(self):
        while 1:
            if (self._paused): continue
            mache_etwas()
            time.sleep(0.1)

und dann kannste mit

Code: Alles auswählen

t._paused = 1
das ganze anhalten und mit

Code: Alles auswählen

t._paused = 0
das ganze wieder starten:

Code: Alles auswählen

t = T()
t.start()

t._paused = 1 # pause
t._paused = 0 # weiter

Verfasst: Mittwoch 24. Dezember 2008, 11:35
von meister56
ok danke für die Hilfe!
mal sehn ob es funktioniert!

Verfasst: Mittwoch 24. Dezember 2008, 11:56
von sma
Birne94 hat geschrieben:

Code: Alles auswählen

        while 1:
            if (self._paused): continue
Dies ist eine ganz üble Warteschleife, die 100% der Rechnenleistung frist und die es zu vermeiden gilt. Es wird auch in Python bessere Wege geben, einen Thread anzuhalten, etwa indem man auf eine Semaphore wartet.

Bei der GUI-Programmierung sollte man lieber auf Threads verzichten, denn fast kein GUI-Rahmenwerk ist threadsafe. Üblicherweise - ich kenne mich mit Python-GUIs leider nicht aus - kann man einen Zeitgeber benutzen, über den man sich einmalig oder periodisch aufrufen kann.

Frohe Weihnachten

Verfasst: Mittwoch 24. Dezember 2008, 12:51
von DasIch
@sma Deswegen ist ja noch das time.sleep mit drin ;) Trotzdem unschön gerade bei GUI Toolkits sollte das mit Events machbar sein, bei PyQt4 ist dass aufjedenfall kein Problem im Thread auf ein Event zu reagieren.

Verfasst: Mittwoch 24. Dezember 2008, 12:56
von Trundle
@DasIch: wenn ``bool(self._paused)`` True ergibt, dann ist da kein sleep drin und es frisst alle Rechenleistung. Außerdem braucht man für periodische Aufrufe eigentlich keine Threads, weil das wirklich jedes Toolkit können müsste.

Verfasst: Mittwoch 24. Dezember 2008, 13:10
von Birne94

Code: Alles auswählen

import threading, time

class T (threading.Thread):
    def __init__(self):
        threading.__init__(self)
        self._paused = 0
    def run(self):
        while 1:
            if (self._paused): continue
            time.sleep(0.1)
            mache_etwas()
stimmt. ist mir auch schon aufgefallen.
und dass es nicht das Beste ist, ist mir auch klar ;-)

Verfasst: Mittwoch 24. Dezember 2008, 13:23
von DasIch
Ändert auch nichts, verwende `pass` statt `continue`.

Verfasst: Mittwoch 24. Dezember 2008, 13:54
von Birne94

Code: Alles auswählen

import threading, time

class T (threading.Thread):
    def __init__(self):
        threading.__init__(self)
        self._paused = 0
    def run(self):
        while 1:
            time.sleep(0.1)
            if (not self._paused):
                mache_etwas()
so besser?

Verfasst: Mittwoch 24. Dezember 2008, 14:02
von lunar
DasIch hat geschrieben:@sma Deswegen ist ja noch das time.sleep mit drin ;) Trotzdem unschön gerade bei GUI Toolkits sollte das mit Events machbar sein, bei PyQt4 ist dass aufjedenfall kein Problem im Thread auf ein Event zu reagieren.
Ich denke, du verwechselt hier Signale mit Ereignissen. Ereignisse, die vom Rahmenwerk (ich wollte dieses Wort auch mal verwenden, sma ;) ) ausgelöst werden, sind keinesfalls threadsicher. Konkret bedeutet das, dass ein PaintEvent z.B. nicht threadübergreifend funktioniert. Es kann daher einzig und allein der Hauptthread auf ein Widget zeichnen. De fakto ist Qt4 genauso wenig threadsicher wie jedes andere GUI-Toolkit. Das ist technisch auch völlig sinnvoll, da paralleles Zeichnen weitreichende Synchronisationsprobleme mit sich bringen würde. Was passiert z.B. wenn zwei Threads parallel auf dieselbe Fläche zeichnen? Das ließe sich nur über komplexes Locking lösen, mit entsprechend negativen Auswirkungen auf die Performance.

Signale und Slots in Qt4 dagegen sind threadsicher (aber eben auch etwas anderes als Ereignisse, deswegen heißen sie ja auch anders ;) ). Allerdings laufen threadübergreifende Verbindungen zwischen Signalen und Slots über eine Queue, Sender und Empfänger leben also in verschiedenen Threads. Wenn z.B. ein QThread ein Signal aussendet, welches mit QLabel.setText verbunden ist (z.B. für eine Statusanzeige), dann läuft QLabel.setText nicht im QThread, sondern im Hauptthread des Programms (der die GUI erzeugt hat) ab.

Im Übrigen wäre ein Thread zur Lösung des gestellten Problems in Qt4 völlig deplaziert, QtCore.QTimer existiert.

Verfasst: Mittwoch 24. Dezember 2008, 14:03
von BlackJack
@meister56: Welches GUI-Toolkit verwendest Du denn nun?