在上一节,我们讲述了最简单最基础的后线程的建立,现在我们将进行拓展
Flask应用中处理异步事件(后台线程+事件循环)的方法(1)
在我们的实际应用当中,我们需要定义三个东西

  1. 一个多线程的信号旗,这里的信号旗指的是多线程编程中一个非常基础且重要的同步工具
    它只有两种状态:
    Clear (清除/未设置): 信号灯是红色的,旗子是放下的。
    Set (设置): 信号灯是绿色的,旗子是举起的。
    当进程调用event.wait(),如果此时事件是 “Clear” 状态(红灯),那么这个线程就会停下来,进入等待状态,被阻塞。

  2. 一个 循环的对象

  3. 一个新线程

接下来在这里我们看到了,有一个target参数,这个就是调用我们的一个说明书

# 1. 创建一个线程同步工具mcp_ready_event = threading.Event()# 2. 创建一个新的 asyncio 事件循环对象background_event_loop = asyncio.new_event_loop()# 3. 创建一个新线程,目标是运行 start_event_loop 函数loop_thread = threading.Thread(target=start_event_loop, args=(background_event_loop, mcp_ready_event),daemon=Truename="name")loop_thread.start() # 启动这个新线程# 4. 主线程在这里暂停,等待后台线程通知logging.info("主线程正在等待 MCP 初始化...")is_ready = mcp_ready_event.wait(timeout=30.0) # 暂停30秒,等待加载

那么我们的说明书怎么写呢?这里举例mcp的连接初始化
初始化这里,无论成功还是失败,初始化流程走完后,调用 .set() 来释放正在 wait() 的主线程。

# ... existing code ...
async def initialize_mcp_connection(ready_event: threading.Event):"""在应用启动时启动MCP服务器并建立一个持久的会话。完成后通过 event 通知主线程。"""# ...try:# 初始化代码except Exception as e:# ... 错误处理 ...finally:logging.info("MCP 初始化过程结束,通知主线程。")ready_event.set() 

初始化完毕之后,我们就进行接下来的开始线程
这里的参数 loop: asyncio.AbstractEventLoop 和 ready_event: threading.Event 是什么意思?
这是一种现代 Python 的语法,叫做 类型提示 (Type Hinting)。它本身不强制任何东西,但它极大地增强了代码的可读性和可维护性,并且能被很多开发工具利用来进行代码检查。

  • loop: asyncio.AbstractEventLoop: 这行代码的意思是,我们期望 loop 这个参数是一个 asyncio.AbstractEventLoop 类型的对象。它告诉任何阅读或调用这个函数的人:“请给我一个 asyncio 的事件循环对象。”
  • ready_event: threading.Event: 同理,这表示我们期望 ready_event 这个参数是一个我们刚才讲的 threading.Event 类型的对象。
def start_event_loop(loop: asyncio.AbstractEventLoop, ready_event: threading.Event):"""在一个线程中启动事件循环,并在启动时安排MCP初始化。"""asyncio.set_event_loop(loop)    loop.create_task(initialize_mcp_connection(ready_event))    logging.info("后台事件循环已启动,MCP 初始化任务已安排。")loop.run_forever()

需要注意这里start_event_loop 函数中的 loop,和主线程中的 background_event_loop,虽然名字不同,但它们指向的是内存中同一个事件循环对象。

最后只需要运行一个专门用于从一个普通线程向一个正在运行 asyncio 事件循环的线程提交任务。

asyncio.run_coroutine_threadsafe(coro, loop):

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/83955.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/83955.shtml
英文地址,请注明出处:http://en.pswp.cn/web/83955.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++(面向对象编程)

思维导图 面向对象 1.面向对象思想 概念:面向对象编程(OOP)是一种以对象为基础的编程范式,强调将数据和操作数据的方法封装在一起。这就是上篇文章讲过的。面向过程是以“怎么解决问题”为核心,而面向对象思想在于“谁…

驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接,

驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接,Error: “The server selected protocol version TLS10 is not accepted by client preferences [TLS13,TLS12]”. ClientConnectionId:d5fd8d69-ae88-4055-9f6d-6e8515224ce2】。 基本上就是…

【三大前端语言之一】交互:JavaScript详解

【三大前端语言之一】交互:JavaScript详解 在学习完HTML和CSS之后,最后一门前端语言——JavaScript,是重中之重。HTML负责页面结构,CSS负责页面样式,而JavaScript则赋予网页“生命”,让网页可以动起来、响…

LangChain面试内容整理-知识点12:检索器(Retriever)接口与实现

在LangChain中,检索器(Retriever)是一个抽象接口,负责根据用户查询从数据源中检索相关文档。可以把Retriever理解为“搜索工具”:给它一个未经结构化的查询文本(如用户问题),它返回一组与之相关的 Document 对象。内部可以基于向量相似度、数据库查询、甚至网络搜索。 …

LLVM前端和优化层

文章目录 LLVM ArchitectueLLVM 前端Lexical Analysis词法分析Syntactic analysis 语法分析Syntactic Analyze语义分析 LLVM 优化层Pass 基础概念Pass 依赖关系Pass API 总结 LLVM Architectue LLVM 前端 LLVM 的前端其实是把源代码也就是 C、C、Python 这些高级语言变为编译器…

工作流和Agent 的区别与联系

工作流和智能体可能让人混淆的地方就是他们都可能有大模型的加持,都可能有工具的加入供大模型调用,本文做一下对比和联系 工作流 (Workflow) 定义: 工作流是一系列预定义、结构化且可重复的步骤或任务,旨在完成特定的业务目标或解…

leetcode--用StringBulider反转字符串单词的巧妙解法

反转字符串中的单词 这道题理想中的操作方式就是先去除前导和尾随空格,之后设一个尾指针,往前检索,扫到一个单词就把这个单词放到字符串的第一个位置。 很明显,java中我们不能直接对字符串进行修改,而我们想实现一个一…

连锁零售行业智慧能源管理解决方案:精准管控,让每一度电创造价值

在连锁超市、便利店等业态中,门店分布广、用能场景复杂、管理成本高是普遍难题。传统能源管理模式依赖人工抄表与分散管理,存在数据滞后、响应效率低、安全隐患难排查等问题。以某全国几千家门店的连锁便利店为例,其面临的挑战包括&#xff1…

在 PostgreSQL 中实现 `lck`, `special`, `item` 与 `org_id` 或 `user_id` 组合唯一的约束

在 PostgreSQL 中实现 lck, special, item 与 org_id 或 user_id 组合唯一的约束 要实现 lck, special, item 这三个字段必须与 org_id 或 user_id 中的一个(但不能同时)组合唯一的约束,你需要创建以下约束: 方案1:使…

g++ a.cpp -o a ‘pkg-config --cflags --libs opencv4‘/usr/bin/ld: 找不到 没有那个文件或目录

这个错误表明 pkg-config 命令没有正确执行,导致编译器无法找到 OpenCV 的库文件和头文件路径。pkg-config 是一个工具,用于查询已安装库的编译和链接选项。如果 pkg-config 无法找到 OpenCV 的配置文件,就会导致这个错误。 以下是解决这个问…

定制平板在智能家居中能做些什么?全面解析其核心功能

大家有没有发现,现在智能家居越来越普及了,很多家庭都在逐步升级自己的居住体验。而在这一过程中,一种设备正悄悄地取代我们以前常用的开关面板和手机APP,成为整个家庭智能控制的核心,这就是——定制平板。 它可不是我…

【通俗易懂】Linux 线程调度策略详解

引言:CPU是厨房,调度器是主厨 要真正理解Linux如何处理成千上万个并发任务,不妨把它想象成一个繁忙的专业厨房。这个比喻不仅能让抽象概念变得具体,更能揭示其背后深刻的设计哲学。 厨房 (The Kitchen): 代表整个计算机系统。 厨…

笔记本电脑安装win10哪个版本好_笔记本装win10专业版图文教程

笔记本电脑安装win10哪个版本好?笔记本还是建议安装win10专业版。Win分为多个版本,其中家庭版(Home)和专业版(Pro)是用户选择最多的两个版本。win10专业版在功能以及安全性方面有着明显的优势,所…

微服务循环依赖调用引发的血案

问题表现 最近的迭代转测后遇到了一个比较有意思的问题。在测试环境整体运行还算平稳,但是过一段时间之后,就开始有接口超时了,日志中出现非常多的 “java.net.SocketTimeoutException: Read timed out”。试了几次重启大法,每次…

LeetCode - 852. 山脉数组的峰顶索引

题目 852. 山脉数组的峰顶索引 - 力扣&#xff08;LeetCode&#xff09; 思路 使用二分查找来定位峰顶 对于中间元素&#xff0c;比较它与其右侧元素的大小&#xff1a; 如果 arr[mid] < arr[mid1]&#xff0c;说明我们在上坡阶段&#xff0c;峰顶在右侧 如果 arr[mid…

国产ARM/RISCV与OpenHarmony物联网项目(二)网关数据显示

本文需要Web服务器开发基础&#xff0c;可参考下述博文&#xff1a; 物联网网关Web服务器--lighttpd服务器部署与应用测试 物联网网关Web服务器--CGI开发接口 一、数据显示界面与功能设计 1、功能设计说明 程序代码结构如下&#xff0c;调用关系见彩色部分标示。 数据显示界面…

Robyn高性能Web框架系列01:Robyn快速入门

Robyn快速入门 安装 Robyn1、仅安装基础 HTTP 路由功能2、带扩展功能的安装 第一个Robyn程序1、创建Robyn应用2、Say Hello!3、启动Robyn应用 Python世界从来不缺少对于性能的追求&#xff0c;Robyn就是其中之一&#xff0c;它将 Python 的异步功能与 Rust 相结合&#xff0c;在…

微信小程序 -----无限新增删除,同时算出总合算金额。

<view class="refuelMoney-main" style="padding-bottom: 200rpx;"><!-- <view class="add_record">添加加油记录</view> --><view class="refuel-itemTextArea"><text style="width: 35%;&quo…

linux “Permission Denied“解决方案

Linux 编译错误排查 在软件开发过程中&#xff0c;编译错误和版本控制问题是开发者每天都会遇到的挑战。本文将结合实际案例&#xff0c;详细讲解 Linux 环境下常见编译错误的排查方法 权限拒绝错误&#xff08;Permission Denied&#xff09; 当执行脚本或程序时&#xff0…

【慧游鲁博】【15】后台管理系统功能完善:仪表盘、多模态交互日志、简单问答词条管理

文章目录 本次更新多模态交互日志效果涉及代码文件 仪表盘&#xff08;部分&#xff09;效果涉及代码文件 简单问答服务词条管理效果涉及代码文件 本次更新 代码真的太多太多了&#xff0c;不放代码了 多模态交互日志 数据概览与筛选功能 时间范围筛选&#xff1a;提供"…