扩展 Python 事件机制:支持等待事件消失

扩展 Python 事件机制:支持等待事件消失

标签:#Python #并发编程 #事件机制 #异步编程

日期:2026-05-19

摘要:Python 的 threading.Event 只能等待事件"发生",但人类的自然认知中,事件应该有"发生"和"消失"两种状态。本文介绍如何扩展事件对象,让它同时支持等待事件发生和等待事件消失,用起来更符合直觉。


前言

在 Python 中,threading.Event 是常用的线程同步机制。但用它的时候,我总感觉哪里不对劲。后来我意识到问题所在:事件有"发生"和"消失"两种状态,但我们只能等待"发生" ,不能等待事件消失。今天就来分享我的解决方案------扩展的事件对象。


一、传统事件机制的痛点

🎯 threading.Event 的用法

python 复制代码
from threading import Event

event = Event()

# 线程A: 设置事件
event.set()  # 事件发生

# 线程B: 等待事件
event.wait()  # 等待事件发生

😅 使用中的别扭感

假设一个场景:等待下载完成,然后下载完成后再等待下载开始。

用传统的方式,你会发现很难表达:

python 复制代码
# 问题:下载完成后,我想等待"下载开始"这个事件再次触发
# 但 set() 之后,wait() 就永远返回了,除非调用 clear()

event = Event()
event.set()  # 下载完成

# 这里我们想等待"下一次下载开始"
# 但 wait() 立即返回,因为事件已经是"发生"状态
event.wait()  # ❌ 立即返回,不是我想要的

核心问题:传统 Event 只有两种状态,但现实中的事件有生命周期:

  • 发生 → 持续 → 消失

我们天然地认为事件有两种等待方式:等它来,或等它走。


二、扩展事件对象的设计

🎯 设计目标

  • 支持两种等待 :
    • wait_appear(): 等待事件发生
    • wait_disappear(): 等待事件消失

💻 实现代码

python 复制代码
import threading
class MyEvent:
    """多线程事件,支持等待事件发生与等待事件消失。"""
    def __init__(self):
        # 内部使用两个 Event,避免轮询
        self._occurred = threading.Event()   # 事件发生时为 True
        self._disappeared = threading.Event() # 事件消失时为 True
        self._disappeared.set()  # 初始状态:事件未发生,消失状态成立
        self._lock = threading.Lock()
    def fire(self):
        """触发事件(设置事件发生)。"""
        with self._lock:
            self._occurred.set()
            self._disappeared.clear()
    def clear(self):
        """清除事件(让事件变为未发生)。"""
        with self._lock:
            self._occurred.clear()
            self._disappeared.set()
    def wait_occur(self, timeout=None)->bool:
        """等待事件发生,直到被 fire() 或超时。
           返回 True 表示事件发生,False 表示超时。
        """
        return self._occurred.wait(timeout)
    def wait_disappear(self, timeout=None)->bool:
        """等待事件消失,直到被 clear() 或超时。
           返回 True 表示事件已消失,False 表示超时。
        """
        return self._disappeared.wait(timeout)
    def is_set(self)->bool:
        """查询当前事件是否处于发生状态。"""
        return self._occurred.is_set()

三、使用示例

python 复制代码
import time
import threading

def worker(evt):
    print("子线程:等待事件发生...")
    if evt.wait_occur(5):
        print("子线程:检测到事件发生,开始工作")
    else:
        print("子线程:超时,事件未发生")
    print("子线程:等待事件消失...")
    if evt.wait_disappear(5):
        print("子线程:事件已消失,后续处理")
    else:
        print("子线程:超时,事件仍未消失")
evt = MyEvent()
t = threading.Thread(target=worker, args=(evt,))
t.start()
time.sleep(1)
evt.fire()          # 触发事件
time.sleep(1)
evt.clear()         # 清除事件
t.join()

四、与传统 Event 的对比

功能 threading.Event Event2
等待事件发生 ✅ wait() ✅ wait_occur()
等待事件消失 ❌ 不支持 ✅ wait_disappear()
链式等待 ❌ 不支持 ✅ 可以支持(等待事件发生之后再消失)
  • 后续还可以加入回调机制

六、总结

📌 本文要点

概念 说明
传统 Event 的局限 只能等待"发生",无法等待"消失"
扩展的 Event2 同时支持 wait_occur() 和 wait_disappear()
可以支持链式等待 wait_appear_then_disappear() / wait_disappear_then_appear()
更符合直觉 事件有生命周期:发生 → 持续 → 消失

📚 参考资料


本文为本人原创,首发于掘金。
如果你有任何问题或想法,欢迎在评论区交流!

相关推荐
第九序言T2 小时前
Python 数据处理进阶(十八)批量处理同结构文件:一个文件夹一次跑完
开发语言·python·自动化·pandas·数据处理
Java后端的Ai之路2 小时前
CAS并发控制-从CPU指令到企业级乐观锁
vue.js·人工智能·python·cas·乐观锁
qq_426003962 小时前
UI自动化高频次登录login限流解决方案
python·ui·自动化
Sakura_j_h_2 小时前
EasyEDA PCB 快速设计Skills
c++·python·github
学长毕设2 小时前
基于springboot的食品仓库管理系统
java·spring boot·后端
滴滴答答哒3 小时前
ASP.NET Core + FaceRecognitionDotNet 人脸识别实战:DI 单例、特征向量持久化与 1:N 比对
后端·asp.net
quantdash_cc3 小时前
如何验证历史行情的交易日期是否完整覆盖研究区间?
python·数据分析·pandas·量化交易·股票数据·quantdash
I Am a robert girl3 小时前
当智能体学会“串通”:从长程交互中读懂涌现式合谋
python·多智能体系统·多智能体协作·llm agent·涌现式合谋·对齐问题·激励机制设计
云和数据.ChenGuang4 小时前
光哥说Python RAG 系统需要哪些评估指标:从检索到生成的全链路评测指南
网络·人工智能·python·算法·langchain
专注仿真5 小时前
线性回归和逻辑回归算法详解
开发语言·人工智能·python·大模型训练·控制算法