在Tkinter中结合Pyrogram与多线程时触发报错问题求助
解决Pyrogram客户端无法正确停止、重复启动报错的问题

问题描述
点击「消息发送」按钮时消息发送正常,点击「停止」按钮后程序看似停止,但Pyrogram客户端并未真正终止,再次点击发送按钮时触发报错。
代码问题分析
- 停止方法未正确执行:原代码中
app.stop仅引用方法未调用,且app.stop()是异步方法,无法在同步的stop函数中直接执行。 - 循环无法立即终止:
async for遍历聊天历史时,即使run设为False,仍会继续遍历剩余条目,无法快速终止流程。 - 重复启动冲突:同一个
Client实例被多次调用start(),前一次客户端未完全释放资源,导致重复启动报错。 - 事件循环管理混乱:复用事件循环且未处理线程间异步调用逻辑,导致后续启动时循环状态异常。
修正后的代码
from customtkinter import * import customtkinter as ctk from threading import Thread import os, asyncio from pyrogram import Client from pyrogram.enums import MessageMediaType run = True path = os.getcwd() app = Client(path + "\\users\\" + "user") tg_task = None # 保存异步任务对象,用于后续取消操作 async def tg_bot(): global run global app, tg_task s = 0 # 仅在客户端未连接时启动 if not app.is_connected: await app.start() try: async for ii in app.get_chat_history(-1002070231241): if not run: break # 立即终止遍历循环 if ii.media == MessageMediaType.VIDEO: s += 1 await app.copy_message(-1002142940185, -1002070231241, ii.id, caption="") print(f"{s} sended.") await asyncio.sleep(1) finally: # 确保客户端最终停止 if app.is_connected: await app.stop() tg_task = None def start(): global run, tg_task run = True # 已有运行任务时,避免重复启动 if tg_task is not None and not tg_task.done(): return def run_loop(): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) global tg_task tg_task = loop.create_task(tg_bot()) try: loop.run_until_complete(tg_task) finally: loop.close() oto = Thread(target=run_loop) oto.daemon = True oto.start() def stop(): global run, tg_task, app run = False # 线程安全地取消异步任务 if tg_task is not None and not tg_task.done(): asyncio.call_soon_threadsafe(tg_task.cancel) # 线程安全地停止客户端 if app.is_connected: loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop.run_until_complete(app.stop()) root = ctk.CTk() root.geometry("300x300") basla = CTkButton(root, text="消息发送", command=start) basla.place(x=75, y=100) dur = CTkButton(root, text="停止", command=stop) dur.place(x=75, y=200) root.mainloop()
关键修改说明
- 正确触发客户端停止:在
stop函数中通过独立事件循环线程安全调用await app.stop(),确保客户端资源完全释放。 - 任务取消逻辑:用
tg_task追踪异步任务,点击停止时直接取消任务,让流程快速终止并执行客户端停止操作。 - 防重复启动:启动前检查任务状态,避免同一客户端实例被重复启动。
- 快速终止循环:在
async for循环内实时判断run状态,一旦触发停止立即跳出循环,提升响应速度。
内容的提问来源于stack exchange,提问作者aev
相关产品推荐
相关产品推荐

