docs: 添加 handler 中使用 threading.Thread 的注意事项
This commit is contained in:
44
README.md
44
README.md
@@ -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 进程崩溃时自动重启,调用方无感知:
|
||||
|
||||
Reference in New Issue
Block a user