1717from time import sleep
1818
1919# ---- Third party imports
20- from qtpy .QtCore import QObject , QThread , Signal
20+ from qtpy .QtCore import QObject , QThread , Signal , Qt
2121
2222# ---- Local imports
2323from qtapputils .qthelpers import qtwait
@@ -28,10 +28,12 @@ class WorkerBase(QObject):
2828 A worker to execute tasks without blocking the GUI.
2929 """
3030 sig_task_completed = Signal (object , object )
31+ sig_run_tasks = Signal ()
3132
3233 def __init__ (self ):
3334 super ().__init__ ()
3435 self ._tasks : OrderedDict [Any , tuple [str , tuple , dict ]] = OrderedDict ()
36+ self .sig_run_tasks .connect (self .run_tasks , Qt .QueuedConnection )
3537
3638 def _get_method (self , task : str ):
3739 # Try direct, then fallback to underscore-prefixed (for backward
@@ -67,7 +69,6 @@ def run_tasks(self):
6769 self .sig_task_completed .emit (task_uuid4 , returned_values )
6870
6971 self ._tasks .clear ()
70- self .thread ().quit ()
7172
7273
7374class TaskManagerBase (QObject ):
@@ -102,9 +103,7 @@ def __init__(self, verbose: bool = False):
102103
103104 @property
104105 def is_running (self ):
105- return not (len (self ._running_tasks ) == 0 and
106- len (self ._pending_tasks ) == 0 and
107- not self ._thread .isRunning ())
106+ return len (self ._running_tasks + self ._pending_tasks ) > 0
108107
109108 def run_tasks (
110109 self , callback : Callable = None , returned_values : tuple = None ):
@@ -134,13 +133,15 @@ def worker(self) -> WorkerBase:
134133
135134 def set_worker (self , worker : WorkerBase ):
136135 """"Install the provided worker on this manager"""
137- self ._worker = worker
138136 self ._thread = QThread ()
137+
138+ self ._worker = worker
139139 self ._worker .moveToThread (self ._thread )
140- self ._thread .started .connect (self ._worker .run_tasks )
140+ self ._worker .sig_task_completed .connect (
141+ self ._handle_task_completed , Qt .QueuedConnection
142+ )
141143
142- # Connect the worker signals to handlers.
143- self ._worker .sig_task_completed .connect (self ._handle_task_completed )
144+ self ._thread .start ()
144145
145146 # ---- Private API
146147 def _handle_task_completed (
@@ -202,22 +203,19 @@ def _run_pending_tasks(self):
202203 print ('Executing {} pending tasks...' .format (
203204 len (self ._pending_tasks )))
204205
205- # Even though the worker has executed all its tasks,
206- # we may still need to wait a little for it to stop properly.
207- i = 0
208- while self ._thread .isRunning ():
209- sleep (0.1 )
210- i += 1
211- if i > 100 :
212- print ("Error: unable to stop {}'s working thread." .format (
213- self .__class__ .__name__ ))
214-
215206 self ._running_tasks = self ._pending_tasks .copy ()
216207 self ._pending_tasks = []
217208 for task_uuid4 in self ._running_tasks :
218209 task , args , kargs = self ._task_data [task_uuid4 ]
219210 self ._worker .add_task (task_uuid4 , task , * args , ** kargs )
220- self ._thread .start ()
211+
212+ self ._worker .sig_run_tasks .emit ()
213+
214+ def close (self ):
215+ if hasattr (self , "_thread" ):
216+ qtwait (lambda : not self .is_running )
217+ self ._thread .quit ()
218+ self ._thread .wait ()
221219
222220
223221class LIFOTaskManager (TaskManagerBase ):
0 commit comments