Python multithreading send a function to run in main thread from subthread and wait for it until finished
<p>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. </p>

<p>The problem is I need to wait for this function is completely finished in main thread, then to proceed the function in subthread. </p>

<p>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?</p>

<p>Thanks very much. I add my running thread method at below</p>

<p>Best Regards,</p>

<pre><code>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]
</code></pre>