|
20 | 20 | if TYPE_CHECKING: |
21 | 21 | from maa.controller import Win32Controller |
22 | 22 |
|
| 23 | +# 退避参数:前 _FAST_RETRY_THRESHOLD 次快速重试(检测瞬断), |
| 24 | +# 之后按 _BACKOFF_S 间隔重试(游戏可能已退出/最小化,无需高频截图)。 |
| 25 | +_FAST_RETRY_THRESHOLD = 3 |
| 26 | +_BACKOFF_S = 5.0 # 连续失败退避间隔(用户要求 5-10s) |
| 27 | +_PERIODIC_LOG_EVERY = 60 # 持续退避中每 N 次失败输出一条进度日志(≈5min 一条) |
| 28 | + |
23 | 29 |
|
24 | 30 | class MeasurementWorker(QObject): |
25 | 31 | """采集循环 worker(moveToThread 到 QThread 运行)。""" |
@@ -57,20 +63,38 @@ def run(self) -> None: |
57 | 63 | self._reset_requested = False |
58 | 64 | self.time_source.reset_timer() |
59 | 65 | try: |
60 | | - img = self.controller.post_screencap().wait().get() |
| 66 | + # 拆开链式调用: wait() 只阻塞不检查状态,需显式判 job.failed。 |
| 67 | + # 否则 C++ 层 screencap failed 时 cached_image 仍返回空/旧图、不抛异常, |
| 68 | + # 导致 except 永远不触发、退避不生效(见 maafw.log 连续刷屏问题)。 |
| 69 | + job = self.controller.post_screencap() |
| 70 | + job.wait() |
| 71 | + if job.failed: |
| 72 | + raise RuntimeError("screencap job failed") |
| 73 | + img = job.get() |
| 74 | + # 防御: MaaFW 有时返回 (0,0,3) 空数组而非抛异常 |
| 75 | + if img is None or img.size == 0: # pyright: ignore[reportUnnecessaryComparison] |
| 76 | + raise RuntimeError("screencap returned empty image") |
61 | 77 | self.time_source.update(img) |
62 | 78 | self._consecutive_errors = 0 |
63 | 79 | except Exception: |
64 | 80 | self._consecutive_errors += 1 |
65 | | - if self._consecutive_errors <= 3: |
66 | | - logger.warning("截图失败 %d 次", self._consecutive_errors) |
67 | | - elif self._consecutive_errors == 4: |
| 81 | + n = self._consecutive_errors |
| 82 | + if n <= _FAST_RETRY_THRESHOLD: |
| 83 | + logger.warning("截图失败 %d 次", n) |
| 84 | + elif n == _FAST_RETRY_THRESHOLD + 1: |
68 | 85 | logger.error( |
69 | | - "截图连续失败 %d 次, 游戏可能已退出或最小化, 降低重试频率", |
70 | | - self._consecutive_errors, |
| 86 | + "截图连续失败 %d 次, 游戏可能已退出或最小化, 降低重试频率至 %.0fs", |
| 87 | + n, |
| 88 | + _BACKOFF_S, |
| 89 | + ) |
| 90 | + elif n % _PERIODIC_LOG_EVERY == 0: |
| 91 | + logger.warning( |
| 92 | + "截图仍连续失败 (%d 次), 每 %.0fs 重试一次", |
| 93 | + n, |
| 94 | + _BACKOFF_S, |
71 | 95 | ) |
72 | | - # 退避: 前 3 次快重试, 之后 5s 一次 |
73 | | - backoff = self.interval_s if self._consecutive_errors <= 3 else 5.0 |
| 96 | + # 退避: 前 N 次快重试, 之后 _BACKOFF_S 一次 |
| 97 | + backoff = self.interval_s if n <= _FAST_RETRY_THRESHOLD else _BACKOFF_S |
74 | 98 | time.sleep(backoff) |
75 | 99 | continue |
76 | 100 |
|
|
0 commit comments