Python中如何实现非阻塞函数调用,避免主程序等待执行完成?
问题解答
1. 用法错误说明
你写的threading和async代码用法都存在错误,才会出现阻塞的情况:
- threading用法错误:你给
Thread的target参数传的是run(),加了括号会立即同步执行run函数,把返回值(这里是None)传给target,相当于你根本没用到多线程,直接在主线程跑了run的逻辑,自然会阻塞。正确的写法是传函数对象本身,不加括号。 - async用法错误:首先
asyncio.run()本身就是阻塞调用,会等待传入的协程执行完成再返回;其次async适用于IO密集型任务,你的run是纯CPU密集计算,全程没有await语句让出事件循环的执行权,协程会一直占用执行资源直到跑完,自然也会阻塞主线程。
2. Python实现非阻塞调用的方案
完全可以实现,根据任务类型选择不同方案:
针对你当前的CPU密集型场景(chunk可见性判断、顶点计算等)
Python的GIL会导致多线程无法并行CPU密集任务,更推荐用多进程或者修正后的多线程(如果计算量不大也可以凑合用):
正确的多线程示例
import threading def run(): n=1 for i in range(10000000): n += 1 print(n) print("Start") # 传函数对象,不加括号 threading.Thread(target=run).start() print("End")
执行输出顺序会是:
Start End 10000001
不会阻塞主线程的执行。
更适合CPU密集场景的多进程示例
多进程可以避开GIL限制,真正并行执行CPU任务,不会挤占主线程的执行资源:
from multiprocessing import Process def run(): n=1 for i in range(10000000): n += 1 print(n) if __name__ == "__main__": print("Start") p = Process(target=run) p.start() print("End") # 不需要等待的话不用调用p.join(),后续可以在合适的时机回收进程资源
额外优化建议
- 不要每次渲染chunk都新建线程/进程,用
concurrent.futures.ThreadPoolExecutor或者ProcessPoolExecutor复用资源,减少创建销毁的开销。 - 子任务计算完的chunk顶点数据用队列传给主线程,主线程每帧从队列取1-2个结果上传到GPU渲染,避免一次性处理大量结果导致帧卡顿。
- 注意主流图形API的上下文只能在创建它的线程使用,不要在子线程里直接调用渲染指令,子线程只做CPU端的计算工作,把结果给主线程提交渲染即可。
内容的提问来源于stack exchange,提问作者Ath.Bar.
相关产品推荐
相关产品推荐

