I got a question about multi-threading in python. Basically in my software, I got one function which is expensive to run. Therefore, I put it to run in subthread. However, during the function running, it will call a function and change some values of a object, which will trigger GUI changes. Therefore, I need to put it back to mainthread.
The problem is I need to wait for this function is completely finished in main thread, then to proceed the function in subthread.
Therefore, I need a clever way to send job back to main thread and wait it finished. Can some one please give me any advise how to do it?
Thanks very much. I add my running thread method at below
Best Regards,
import Queue
import logging
import sys
import time
import threading
DISABLE_THREADING = False
queue = Queue.Queue()
def run_in_sub_thread_named(name, function, *params):
if DISABLE_THREADING:
return function(*params)
th = _DEThread(function, *params)
task_info = TaskInfo(name)
th.task_info = task_info
running_tasks[th] = task_info
th.start()
return th
def run_in_main_thread(function, *params, **kwargs):
cur_thread = threading.currentThread()
cur_thread_name = cur_thread.getName()
in_main_thread = (cur_thread_name == 'MainThread')
if in_main_thread:
function(*params, **kwargs)
else:
queue.put((function, params, kwargs))
class _DEThread:
def __init__(self, function, *params):
self.thread = threading.Thread(target=self.execute)
self.thread.setDaemon(True)
self.function = function
self.params = params
self.name = ''
def start(self):
self.thread.start()
def execute(self):
try:
if self.params is ():
res = self.function()
else:
res = self.function(*self.params)
except:
run_in_main_thread(self._update_task_info,
'Exception: %s' % repr(sys.exc_info()))
raise
run_in_main_thread(self._update_task_info, res)
def _update_task_info(self, res):
if self in running_tasks:
task_info = running_tasks[self]
task_info.end_time = time.time()
task_info.result = res
finished_tasks[self] = task_info
del running_tasks[self]
Typically, the way to call functions between threads in Qt is with Signals and Slots. You can also use QMetaObject.invokeMethod
to call a function in another thread, and use the Qt.BlockingQueuedConnection
type to force it to block the thread until the main thread function completes. You're going to need to use QThreads
instead of python threads
though. Take a look at the Worker pattern described in the QThread
docs to see how to refactor your code to work with QThreads
def function_in_thread(self):
# This will block the thread until function completes
# in main thread.
QtCore.QMetaObject.invokeMethod(self.main_gui, 'nameOfMethod', QtCore.Qt.BlockingQueuedConnection)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With