我正处于从客户那里收到消息的情况。在处理该请求的函数(@socketio.on)中,我想调用一个完成一些繁重工作的函数。这不应该导致阻塞主线程,并且认为一旦完成工作,就会通知客户机。因此,我开始了一个新的线程。
现在我遇到了一个非常奇怪的行为:
消息永远不会到达客户机。但是,代码到达发送消息的特定位置。
更令人惊讶的是,如果线程中除了发送给客户机的消息之外没有发生任何事情,那么答案实际上会找到通向客户机的路。
总而言之:
如果在发送消息之前发生了一些计算密集型的事情,则它不会被传递,否则就是。
就像上面说的here和here一样,从线程向客户端发送消息根本不是问题:In all the examples shown until this point the server responds to an event sent by the client. But for some applications, the server needs to be the originator of a message. This can be useful to send notifications to clients of events that originated in the server, for example in a background thread.
这是一个示例代码。当移除注释锐器(#)时,消息('foo from thread')无法到达客户端,否则它会找到。from flask import Flask
from flask.ext.socketio import SocketIO, emit
app = Flask(__name__)
socketio = SocketIO(app)
from threading import Thread
import time
@socketio.on('client command')
def response(data):
thread = Thread(target = testThreadFunction)
thread.daemon = True
thread.start()
emit('client response', ['foo'])
def testThreadFunction():
# time.sleep(1)
socketio.emit('client response', ['foo from thread'])
socketio.run(app)
我使用的是Python 3.4.3,Flask 0.10.1,Flask-socketio1.2,eventlet 0.17.4。
此示例可以复制并粘贴到.py文件中,并且行为可以立即复制。
有人能解释一下这种奇怪的行为吗?
更新
这似乎是一个小插曲。如果我这样做了:socketio = SocketIO(app, async_mode='threading')
它强制应用程序不使用eventlet,尽管它已安装。
但是,对于我来说,这不是一个适用的解决方案,因为使用“线程”作为异步模式拒绝接受二进制数据。每次我从客户端向服务器发送二进制数据时,它都会说:
WebSocket transport not available. Install eventlet or gevent and gevent-websocket for improved performance.
第三个选项,使用gevent作为异步模式对我不起作用,而且gevent还不支持python 3。
还有其他建议吗?