2017-06-05 957 views
1

在我的瓶應用程序,我有一個類似的循環,由客戶端發出的插座消息發佈:python socketio和Flask:如何在後臺線程中停止循環?

@socketio.on('start') 
def my_start(): 
    global thread 
    if thread is None: 
     thread = socketio.start_background_task(target=background_thread)  

def background_thread(): 
     for i in range(1,100): 
      socketio.emit('my_mess',{'data': i}) 
      if <**condition**>== True: 
       socketio.emit('aborted') 
       break 
     if <**condition**> == False: 
      socketio.emit('Success',{'data': '16.34 GB'}) 
     else: 
      <**condition**> = False 

的問題是:我怎麼可以停止/中止來自客戶端的循環?我嘗試設置「中止」消息,但它不起作用。換句話說,我如何使用我在代碼中草擬的<**condition**>

+0

任何這運氣?我看起來很相似;)。 – zamber

+0

我面臨着同樣的問題(需要能夠中斷向客戶端發送消息的while循環;我需要用另一個套接字調用來中斷它)。這個例子[鏈接](https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/example/app.py#L17)使用後臺線程來運行這樣的循環。所以使用多線程可能是一個解決方案。 – VilleLipponen

回答

2

這是我的實現。

Server代碼:

#!/usr/bin/env python 

# make sure to use eventlet and call eventlet.monkey_patch() 
import eventlet 
eventlet.monkey_patch() 

from flask import Flask, render_template, request, g, session, make_response, current_app, redirect, url_for 
from flask_socketio import SocketIO, emit 

app = Flask(__name__) 
app.config['SECRET_KEY'] = "secret" 

# make sure to set the async_mode as 'eventlet' 
socketio = SocketIO(app, async_mode='eventlet') 


# our gloabal worker 
workerObject = None 

class Worker(object): 

    switch = False 
    unit_of_work = 0 

    def __init__(self, socketio): 
     """ 
     assign socketio object to emit 
     """ 
     self.socketio = socketio 
     self.switch = True 

    def do_work(self): 
     """ 
     do work and emit message 
     """ 

     while self.switch: 
      self.unit_of_work += 1 

      # must call emit from the socket io 
      # must specify the namespace 
      self.socketio.emit("update", {"msg": self.unit_of_work}, namespace="/work") 

      # important to use eventlet's sleep method 
      eventlet.sleep(1) 

    def stop(self): 
     """ 
     stop the loop 
     """ 
     self.switch = False 


@app.route('/') 
def index(): 
    """ 
    renders demo.html 
    """  
    return render_template('demo.html') 



@socketio.on('connect', namespace='/work') 
def connect(): 
    """ 
    connect 
    """ 

    global worker 
    worker = Worker(socketio) 
    emit("re_connect", {"msg": "connected"}) 


@socketio.on('start', namespace='/work') 
def start_work(): 
    """ 
    trigger background thread 
    """ 

    emit("update", {"msg": "starting worker"}) 

    # notice that the method is not called - don't put braces after method name 
    socketio.start_background_task(target=worker.do_work) 


@socketio.on('stop', namespace='/work') 
def stop_work(): 
    """ 
    trigger background thread 
    """ 

    worker.stop() 
    emit("update", {"msg": "worker has been stoppped"}) 



if __name__ == '__main__': 
    """ 
    launch server 
    """ 
    socketio.run(app, host="0.0.0.0", port=5000, debug=True) 

客戶端代碼:

<!DOCTYPE HTML> 
<html> 
    <head> 
     <title>Demo - background worker</title> 

     <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script> 
     <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.5/socket.io.min.js"></script> 

     <script type="text/javascript" charset="utf-8"> 

      $(document).ready(function() { 

       var socketio = null; 
       var namespace = "/work" 
       $("input[name='connect']").on("click", function() { 

        console.log("connect"); 

        socketio = io.connect(
          location.protocol  + 
          '//'     + 
          document.domain   + 
          ':'      +  
          location.port   + 
          namespace    
         ); 

        socketio.off().on("re_connect", function(msg) { 
         $(".report").append(msg.msg + "<br />"); 
        }); 
       }); 

       $("input[name='start']").on("click", function() { 
        socketio.emit("start"); 
        socketio.on("update", function(msg) { 
         $(".report").append(msg.msg + "<br />"); 
        }); 
       }); 

       $("input[name='stop']").on("click", function() { 
        socketio.emit("stop"); 
        socketio.on("update", function(msg) { 
         $(".report").append(msg.msg + "<br />"); 
        }); 
       }); 


      }); 

     </script> 

    </head> 

    <body> 
     <div class="main_container" > 

      <div class="control"> 

       <form id="ctrl_form"> 
        <input type="button" name="connect" value="connect" /> 
        <input type="button" name="start" value="start" /> 
        <input type="button" name="stop" value="stop" /> 

       </form> 
      </div> 

      <div class="report"> 
       ... 
      </div> 
     </div> 
    </body> 
</html>