fix: 重试计时不准,修复Tkinter after()延迟问题\n\n根因:Tkinter的after()在窗口非活动时会延迟触发,\n导致实际重试间隔不是准确的5秒,可能变成十几秒甚至更长。\n\n修复:记录目标重试时间,执行前验证是否真的到了时机。\n若未到,重新调度;若已到,执行重试。\n这样确保重试间隔是实打实的5秒,不是虚的5秒。

This commit is contained in:
youpaishidifu
2026-08-20 08:58:03 +08:00
parent 589e277419
commit 29f3738c09
+18 -2
View File
@@ -1182,14 +1182,27 @@ class MsgBotApp(ctk.CTk):
def _execute_reply(self, data: dict):
"""主线程执行自动回复发送。加上发送锁防止监控轮询干扰。
自动重试:失败后延缓5秒重试,连续3次失败视为用户接管,退避本轮。
⭐ 2026-08-20 修复:记录目标重试时间,防止Tkinter after()延迟导致计时不准。
"""
import time as _time
platform = data["platform"]
answer = data["answer"]
sender = data.get("sender")
msg = data.get("msg", "")
max_retries = 3
retry_delay = 5 # 秒
attempt = data.get("_attempt", 0) # ⭐ 主线程异步重试计数(不阻塞GUI)
attempt = data.get("_attempt", 0)
# ⭐ 验证重试时机:若目标时间未到,重新调度(防止after()延迟)
if attempt > 0:
_retry_at = data.get("_retry_at", 0)
_now = _time.time()
if _now < _retry_at:
_remaining = int((_retry_at - _now) * 1000)
logger.debug(f"[{platform}] 重试时机未到({_remaining}ms),重新调度")
data["_retry_at"] = _retry_at
self.after(_remaining, lambda d=data: self._execute_reply(d))
return
# ⭐ 发送前强制检查时间戳:≤300秒则发送,≥300秒则丢弃
msg_age = self._check_message_freshness(msg)
@@ -1213,11 +1226,14 @@ class MsgBotApp(ctk.CTk):
return # 成功直接退出
else:
if attempt < max_retries - 1:
# ⭐ 记录目标重试时间,确保重试间隔准确
_retry_at = _time.time() + retry_delay
data["_attempt"] = attempt + 1
data["_retry_at"] = _retry_at
self._log(f"[{platform}] ⚠ 自动回复发送失败,{retry_delay}秒后重试({attempt+1}/{max_retries})")
# ⭐ 2026-08-17 修复GUI冻结:原实现主线程 time.sleep(5) ×3 = 界面冻结15秒+
# 窗口不前置时 _paste_and_send 必失败,用户跟踪日志时 GUI 无响应。
# 改为 after() 异步重试:主线程立即返回,5秒后再执行,界面保持流畅。
data["_attempt"] = attempt + 1
self.after(int(retry_delay * 1000), lambda d=data: self._execute_reply(d))
else:
self._log(f"[{platform}] ⚠ 自动回复发送失败(连续{max_retries}次),用户可能在接管,本轮跳过")