websocket 在Flask应用程序上下文中使用线程

brgchamk  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(178)

我试图将应用程序上下文推送到线程,线程完成了一个冗长的任务,然后发送一个WebSocket来提醒它已经完成。因为我正在使用一个线程,所以我在JavaScript中创建的侦听'completed'事件的套接字由于某种原因无法接收它,当我删除线程时,它一切正常。以下是我尝试过但失败的解决方案:
routes.py

import threading
from main import socketio
from flask import current_app

@app.route('/threading')
def threading():
    return render_template('threading.html')

def simulate_long_task(app_context):
        app_context.push() 
        print(app_context)
        print("Long task started...")
        time.sleep(5)  # Simulate a long task (5 seconds)
        print("Long task completed!")
        socketio.emit('completed', {"message": "Hello"})

@socketio.on('connect')
def handle_connect():
    print('User connected')

@socketio.on('start_task')
def start_long_task():
    print(current_app.app_context())
    task_thread = threading.Thread(target=simulate_long_task, args=(current_app.app_context(),), daemon=True)
    task_thread.start()

threading.html

<!DOCTYPE html>
<html>
<head>
    <title>WebSocket Example</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.7.2/socket.io.js"></script>
</head>
<body>
    <h1>WebSocket Example</h1>
    <button id="startButton">Start Long Task</button>
    <div id="messages"></div>
    
    <script>
        var socket = io.connect();

        socket.on('connect', function() {
            console.log("Connected To Websocket")
            document.getElementById('startButton').addEventListener('click', function() {
                socket.emit('start_task');
            });
        });

        socket.on('completed', function(data) {
            console.log("Received completed event:", data.message);
            // Handle the data as needed
        });

        socket.on('disconnect', function() {
            console.log('Disconnected From Websocket');
        });
    </script>
</body>
</html>

我使用Flask-SocketIO作为websockets。WebSocket连接正常,用户可以正常连接。唯一的问题是涉及线程的时候。
我会感谢任何帮助,我可以得到这一点,因为我已经尝试推动的背景下,并尝试了各种解决方案,从别人,但没有工作。

xt0899hw

xt0899hw1#

我不知道为什么你的应用程序不工作。我注意到,通过定义一个threading函数,使用相同的标识符覆盖了导入的模块。
基本上,您不需要应用程序上下文来发回消息。例如,只有当您在线程内访问数据库时,才需要这样做。
如果您确实需要应用程序上下文,这里有一个示例。

from flask import (
    Flask, 
    current_app, 
    render_template
)
from flask_socketio import SocketIO

app = Flask(__name__)
app.secret_key = 'your secret here'
sio = SocketIO(app)

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

def background_task(app):
    with app.app_context():
        # Work within the application context.
        pass
    sio.sleep(5)
    sio.emit('completed', { 'message': 'Hello' })

@sio.on('connect')
def connect():
    print('User connected')

@sio.on('start-task')
def start_task():
    print('Start background task')
    sio.start_background_task(
        background_task, 
        current_app._get_current_object()
    )

if __name__ == '__main__':
    sio.run(app)
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Websocket Example</title>
</head>
<body>

    <h1>WebSocket Example</h1>
    <button id="start-btn">Start Long Task</button>
    <div id="messages"></div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.7.2/socket.io.js"></script>
    <script type="text/javascript">
        (function() {
            var socket = io();
            socket.on('connect', () => {
                console.log('Connected to Websocket');
                document
                    .getElementById('start-btn')
                    .addEventListener('click', () => {
                        socket.emit('start-task');
                    });
            });

            socket.on('completed', (data) => {
                console.log(data.message);
            });

            socket.on('disconnect', () => {
                console.log('Disconnected from Websocket');
            });
        })();
    </script>
</body>
</html>

相关问题