You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Streamlit中启动线程后无法点击停止按钮的问题?

问题解决方法

核心错误分析

你的代码存在两个关键问题,导致无法正常点击Stop按钮:

  1. 线程创建逻辑错误:store()方法里,threading.Thread(target=self.run())是直接调用了run()函数,而非传递函数对象给target参数。这会让主线程直接进入run()的无限循环,完全阻塞,根本没启动新线程。
  2. Streamlit状态丢失:Streamlit每次交互(点击按钮)都会重新运行整个脚本,原有的Test实例会被重新创建,导致无法获取到之前启动的线程对象。

修改后的代码

1. 修正Test类的线程逻辑

import threading
import time
 
class Test():
    def __init__(self) -> None:
        self.stop_threads = False
        self.t1 = None  # 提前初始化线程对象变量
    
    def run(self):
        # 优化循环条件,提前判断停止标志
        while not self.stop_threads:
            print('thread running')
            time.sleep(5)
            
    def store(self):  
        # 修复target参数:传递函数对象而非直接调用函数
        self.t1 = threading.Thread(target=self.run)
        self.t1.start()

    def stop(self):    
        # 先判断线程是否存在且存活
        if self.t1 and self.t1.is_alive():
            self.stop_threads = True
            self.t1.join()
            self.stop_threads = False  # 重置状态,方便下次启动
            print('thread killed')

2. 修正Streamlit界面的状态保存逻辑

from test2 import Test
import streamlit as st

# 使用session_state保存Test实例,避免每次交互重新创建对象
if 'test_obj' not in st.session_state:
    st.session_state.test_obj = Test()

obj = st.session_state.test_obj

if st.button("Run"):
    # 防止重复启动线程
    if not obj.t1 or not obj.t1.is_alive():
        obj.store()
        st.success("线程已启动")

if st.button("Stop"):
    obj.stop()
    st.success("线程已停止")

关键修改说明

  • 线程创建修正:target=self.run传递的是函数引用,让子线程去执行run逻辑,主线程不会被阻塞。
  • 循环条件优化:将while True改为while not self.stop_threads,设置停止标志后无需等待sleep结束就能退出循环。
  • Streamlit状态管理:通过st.session_state保存Test实例,确保每次交互操作的是同一个对象,能正确获取到已启动的线程。
  • 重复启动防护:判断线程是否存活,避免多次点击Run按钮创建多个重复线程。

内容的提问来源于stack exchange,提问作者Myron Dsilva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 13:15:19