0

我正在创建一个 Web 应用程序,它应该实时更新推送到数据库的读数,为此我必须让一个方法在用户访问页面时在后台运行。数据是特定于用户的,因此仅添加后台线程无济于事。不过,困难的部分是我需要能够在按下按钮时停止线程,并在使用不同的数据后立即重新启动它。我尝试使用 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)

我的问题是,虽然代码有效,并且它确实更新了前端,但我似乎无法弄清楚如何专门为一个用户创建这个线程(如果有必要的话)。以及如何从另一个套接字方法停止线程并在其位置启动一个新方法。

4

1 回答 1

1

当您收到一个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)

要停止后台线程,您必须跟踪所有线程并跟踪每个线程所属的用户。在线程循环中,您将需要一个 boolean 而不是 just while True,这样您就可以通过切换该 boolean 的值来告诉线程停止。我建议您为您的线程创建一个类包装器,并stop()在其中添加一个更改布尔值的方法,然后等待线程通过调用thread.join().

于 2016-06-07T14:27:57.717 回答