2016-05-19 2 views
0

Je crée une application web qui devrait mettre à jour les lectures poussées vers la base de données en temps réel, pour cela, je dois garder une méthode en arrière-plan chaque fois qu'un utilisateur la page. Les données sont spécifiques à l'utilisateur, il suffit donc d'ajouter un thread d'arrière-plan. La partie difficile, cependant, est que je dois être en mesure d'arrêter le fil sur un bouton, et le redémarrer tout de suite après avec des données différentes. J'ai essayé de créer une solution avec eventlet gunicorn et flacon-socketio qui ressemble un peu à ceci:Mettre à jour les données spécifiques à chaque utilisateur en utilisant flask-socketio et eventlet

@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) 

mon problème est que si le code fonctionne, et il ne met à jour la fin avant que je ne peux pas l'air d'être capable de comprendre exactement comment créer ce thread pour un utilisateur en particulier (si cela est même nécessaire). Et comment arrêter le thread d'une autre méthode de socket et en commencer un nouveau à sa place.

+0

Avez-vous un moyen d'identifier l'utilisateur? Par exemple, avez-vous le nom d'utilisateur ou l'identifiant dans la session? – Miguel

+0

Vérifiez la nécessité de la création de threads avant 'thread = Thread (...)'? – temoto

+0

@Miguel J'ai un identifiant utilisateur dans la session que j'utilise pour identifier un utilisateur, c'est l'ObjectID du backend mongodb que j'utilise. –

Répondre

0

Lorsque vous obtenez un événement connect, vous pouvez mapper votre ID utilisateur de base de données sur l'ID de session SocketIO. Quelque chose comme ceci:

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) 

A partir de là, quand vous voulez émettre à un utilisateur individuel, il suffit d'ajouter room=user.sid à votre appel emit. Dans votre exemple:

@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) 

Pour arrêter un fil d'arrière-plan, vous devez garder une trace de tous et de garder une trace de chaque utilisateur qui appartient à des fils. Dans la boucle de threads, vous aurez besoin d'un booléen au lieu de simplement while True, afin que vous puissiez dire au thread de s'arrêter en changeant la valeur de ce booléen. Je vous recommande de créer un wrapper de classe pour votre thread et d'y ajouter une méthode stop() où le booléen est modifié, puis vous attendez que le thread se termine en appelant thread.join().

+0

Je l'ai fait, et cela semble fonctionner parfaitement, merci pour l'aide et la bonne réponse. Pour ceux qui se demandent à l'avenir, j'ai créé un fil stoppable selon la réponse dans [link] (http://stackoverflow.com/questions/27102881/python-threading-self-stop-event-object-is-not-callable) 'cette question. Marquage comme répondu pour l'instant, merci encore. –