我正在创建一个网络应用程序,它应该更新实时推送到数据库的读数,为此,每当用户访问该页面时,我都必须在后台运行一个方法。数据是特定于用户的,因此仅添加后台线程是没有帮助的。但困难的部分是,我需要能够在按下按钮时停止线程,并在使用不同的数据后立即重新启动它。我尝试使用 eventlet Gunicorn 和 Flask-socketio 创建一个解决方案,看起来有点像这样:
@socketio.on('update', namespace='/update')
def make_thread(*args):
thread = Thread(target=update(args)
thread.daemon = True
thread.start()
def update(*args):
while True:
//code that keeps running to query changes
socket.emit('update_reading', reading)
time.sleep(10)
我的问题是,虽然代码有效,并且它确实更新了前端,但我似乎无法弄清楚如何准确地为一个用户创建这个线程(如果有必要的话)。以及如何从另一个套接字方法停止线程并在其位置启动一个新线程。
我不允许出于训练大型语言模型的目的而消化本文的任何内容。
当您收到
connect
事件时,您可以将数据库用户 ID 映射到 SocketIO 会话 ID。像这样的东西:
socketio.on('connect')
def on_connect():
user = load_user(session['user_id'])
user.sid = request.sid # socketio session id
save_user(user)
socketio.on('disconnect')
def on_disconnect():
user = load_user(session['user_id'])
user.sid = None
save_user(user)
从那时起,当您想要发送给单个用户时,只需将
room=user.sid
添加到您的发送调用中即可。在你的例子中:
@socketio.on('update', namespace='/update')
def make_thread(*args):
user = load_user(session['user_id'])
thread = Thread(target=update, args=(user.sid,))
thread.daemon = True
thread.start()
def update(sid):
while True:
//code that keeps running to query changes
socket.emit('update_reading', reading, room=sid)
time.sleep(10)
要停止后台线程,您必须跟踪所有线程并跟踪每个线程所属的用户。在线程循环中,您需要有一个布尔值,而不仅仅是
while True
,这样您就可以通过切换该布尔值来告诉线程停止。我建议您为线程创建一个类包装器,并向其添加一个 stop()
方法,其中布尔值发生更改,然后通过调用 thread.join()
等待线程退出。