首页 > 解决方案 > Python线程:等待线程停止然后执行函数

问题描述

我试图在我的线程完成后运行一个函数,但该函数没有被调用。代码结构:

class():

    def functiontocall()  # uses data calculated in thread for plotting. only works when thread is complete
        do something with self.A

    def watchthread():
        thread()
        functiontocall()
        # since this function depends on variable A, it throws an error.
        # I tried: if thread.join == True: functiontocall but this did not call the function.

    def thread():
        def run():
            pythoncom.CoInitialize()
            --- do stuff --
            for i in 1000:
                thousands of calculations while updating state in GUI ---
            A = result
            self.A = A
        thread = threading.Thread(target=run)
        thread.start()

注意:为简单起见,我删除了“自我”。

thread.join 应该告诉我线程何时完成,但由于某种原因我仍然无法运行 functiontocall。

这是一般组织线程的坏方法吗?

编辑:我可以在线程完成后调用该函数,但在线程运行时我无法访问变量。例如,我的 GUI 中进度条的进度为 0-100%。当我使用:

def watchthread():
    thread()
    thread.join()
    functiontocall()

我无法在我的 GUI 中更新线程的状态。它只是等到计算完成然后运行functiontocall()。

标签: pythonpython-multithreading

解决方案


因为您正在使用线程,一旦线程启动 Python 将继续执行下一步操作,除非您要求,否则它不会等待线程完成。

使用您的代码,如果您想在继续之前等待线程函数完成,那么听起来您不需要线程,正常的函数将运行,完成,然后 Python 将继续运行 functiontocall()

如果有原因需要使用示例中没有遇到的线程,那么我建议使用 thread.join()

threads = []  # list to hold threads if you have more than one
t = threading.Thread(target=run)
threads.append(t)

for thread in threads:  # wait for all threads to finish
    thread.join() 

functiontocall()  # will only run after all threads are done

同样,我建议重新考虑线程是否是您需要在这里使用的,因为它似乎并不明显。

要根据新信息更新此答案,这可能是您希望变量可访问的方式。在这种情况下,线程都会更新您的类变量 A,您的 GUI 更新函数也会定期读取它并更新您的 GUI。

class ThisClass():

    def __init__(self):
        self.A = 0

    def function_to_call(self):
        while self.A != 100:  # assuming this is a progress bar to 100%
            # update in GUI

    def run(self):
        # does calculations
        with lock: # to prevent issues with threads accessing variable at the same time
            self.A += calculations

    def progress(self):
        threads = []  # list to hold threads if you have more than one
        t = threading.Thread(target=run)
        threads.append(t)

        f = threading.Thread(target=self.function_to_call)
        threads.append(f)

        for thread in threads:
            thread.start()

        for thread in threads:  # wait for all threads to finish
            thread.join()

推荐阅读