docs: 添加 handler 中使用 threading.Thread 的注意事项

This commit is contained in:
2026-04-14 16:49:12 +08:00
parent b4e77ce9a8
commit 30004e44ee

View File

@@ -186,6 +186,50 @@ def slow_compute(n: int) -> int:
> 限制:长时间不释放 GIL 的 C 扩展(如大规模 numpy 矩阵运算)无法被中断,需等其释放 GIL 后才触发。
## 注意事项
### 在 handler 中使用 `threading.Thread`
handler 函数内部可以启动后台线程,但行为取决于是否等待:
```python
# ✅ fire-and-forget立即返回连接立即释放后台线程独立运行
@expose
def do_something():
threading.Thread(target=long_task, daemon=True).start()
return "ok"
# ⚠️ 等待线程:连接被占用直到线程结束,等同于直接在 handler 里执行
@expose
def do_something():
t = threading.Thread(target=long_task)
t.start()
t.join() # 连接在此阻塞
return "ok"
```
**`call_go()` 只能在 handler 的原始线程中调用。** `call_go()` 依赖线程局部变量 `_local.mux` 获取当前连接,后台线程中该变量不存在,调用会抛出 `RuntimeError`
```python
@expose
def do_something():
def bg():
call_go("Method") # ❌ RuntimeError: call_go() must be called within a gobridge handler
threading.Thread(target=bg, daemon=True).start()
return "ok"
```
如果后台线程的结果需要回调 Go应在 handler 线程中通过 `queue.Queue` 等待后台线程结果后再调用:
```python
@expose
def do_something():
result_q = queue.Queue()
threading.Thread(target=lambda: result_q.put(compute()), daemon=True).start()
result = result_q.get() # 等待后台线程
return call_go[str]("Process", result) # ✅ 在 handler 线程中调用
```
## 进程自动重启
Python worker 进程崩溃时自动重启,调用方无感知: