ich habe ein Programm, das fünf Threads startet. Jeder einzelne Thread gibt „Hello World!“ auf der Konsole aus. Jeder Thread wartet via
eine zufällige Zeit. Am Ende eines Threads sollte eine Callback-Funktion aufgerufen werden. Diese gibt „Goodby folks“ auf der Konsole aus.time.sleep()
Um zu zeigen, dass das Threading funktioniert, werden die Laufzeiten jedes einzelnen Threads gemessen. Zum Vergleich wird auch die Gesamtlaufzeit gemessen des Programms.
Die Gesamtlaufzeit entspricht der Laufzeit des am längsten laufenden Threads. Aber die Ausgabe „Auf Wiedersehen Leute“ fehlt alle fünf Male. Das heißt, aus einem mir unbekanntem Grund, wird die Callback-Funktion nicht aufgerufen bzw. erreicht.
Hat einer von Euch einen Tip für mich, wo hier mein Denkfehler liegt?
Die Ausgabe sieht so aus, leider eben ohne 'Goodby folks':
Code: Alles auswählen
saying Hello World! took 0.126 s
saying Hello World! took 0.439 s
saying Hello World! took 0.645 s
saying Hello World! took 0.994 s
saying Hello World! took 1.469 s
total runtime is 1.479 s
Code: Alles auswählen
import random
import sys
import time
from typing import Callable
from PyQt5.QtCore import QCoreApplication, QThread, QObject, pyqtSignal
class MeasureRuntime:
def __enter__(self):
self.__start = time.perf_counter()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.__stop = time.perf_counter()
self.elapsed = self.__stop - self.__start
return True
class MyQtThreads(QObject):
def __enter__(self):
self.__running_threads: list = []
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.__waitForThreadsListEmpty()
return True
def __waitForThreadsListEmpty(self):
while self.__running_threads:
for thread in self.__running_threads:
if thread.isFinished():
self.__running_threads.pop(self.__running_threads.index(thread))
def doInThread(self, fn, *args, callback: Callable = None, **kwargs) -> int:
thread = MyQtThread(fn, *args, **kwargs)
if callback:
thread.SIG_FINISHED.connect(callback)
self.__running_threads.append(thread)
thread.start()
return id(thread)
class MyQtThread(QThread):
SIG_FINISHED = pyqtSignal(object)
def __init__(self, fn, *args, **kwargs):
super().__init__()
self.fn = fn
self.args = args
self.kwargs = kwargs
def run(self):
ret = self.fn(*self.args, **self.kwargs)
result_info = {"thread_id": id(self), "args": ret}
self.SIG_FINISHED.emit(result_info)
def say_hello():
with MeasureRuntime() as rt:
random.seed()
time.sleep(random.random()*3)
print(f'saying Hello World! took ', end='')
print(f'{rt.elapsed:.3f} s')
def say_adieu(args):
print('Goodby folks')
class Main(QThread):
def __init__(self):
super().__init__()
def run(self):
print()
with MeasureRuntime() as rt:
with MyQtThreads() as threads:
for _ in range(5):
threads.doInThread(say_hello, callback=say_adieu)
print(f'\ntotal runtime is {rt.elapsed:.3f} s')
if __name__ == '__main__':
qcoreapp = QCoreApplication(sys.argv)
thread = Main()
thread.finished.connect(qcoreapp.exit)
thread.start()
qcoreapp.exec()