feat: 优化异常处理,新增日志记录

This commit is contained in:
2026-01-19 17:48:49 +08:00
parent 0ab770d464
commit d421b9b72b
3 changed files with 182 additions and 91 deletions

View File

@@ -18,6 +18,12 @@ namespace TimerApp
private int _restElapsedSeconds;
private bool _isPaused;
private bool _disposed;
// 状态检测缓存
private int _checkTickCounter;
private const int CheckIntervalTicks = 3; // 每3秒检查一次空闲/媒体状态
private long _cachedIdleMs;
private bool _cachedMediaPlaying;
// 配置 (默认值)
public TimeSpan WorkDuration { get; set; } = TimeSpan.FromMinutes(20);
@@ -45,6 +51,8 @@ namespace TimerApp
public void Start()
{
// 启动时立即触发一次检测
_checkTickCounter = CheckIntervalTicks;
_timer.Start();
ResetWork();
}
@@ -71,96 +79,116 @@ namespace TimerApp
private void Timer_Tick(object? sender, EventArgs e)
{
// 如果处于暂停状态,不处理计时逻辑
if (_isPaused)
try
{
return;
}
long idleMs = NativeMethods.GetIdleTime();
TimeSpan idleTime = TimeSpan.FromMilliseconds(idleMs);
if (CurrentState == MonitorState.Resting)
{
// 休息模式逻辑
// 使用计数器而不是时间差,避免秒数跳变
_restElapsedSeconds++;
int totalRestSeconds = (int)RestDuration.TotalSeconds;
int remainingSeconds = totalRestSeconds - _restElapsedSeconds;
if (remainingSeconds <= 0)
// 如果处于暂停状态,不处理计时逻辑
if (_isPaused)
{
// 休息结束
RestEnded?.Invoke(this, EventArgs.Empty);
ResetWork(); // 重新开始工作周期
return;
}
else
long idleMs;
TimeSpan idleTime;
// 优化降低系统API调用频率
// 每 CheckIntervalTicks (3) 秒更新一次状态
_checkTickCounter++;
if (_checkTickCounter >= CheckIntervalTicks)
{
TimeSpan remainingRest = TimeSpan.FromSeconds(remainingSeconds);
RestProgressChanged?.Invoke(this, remainingRest);
_checkTickCounter = 0;
_cachedIdleMs = NativeMethods.GetIdleTime();
_cachedMediaPlaying = NativeMethods.IsMediaPlaying();
}
}
else
{
// 检测是否有视频/媒体正在播放
bool isMediaPlaying = NativeMethods.IsMediaPlaying();
// 工作/空闲模式逻辑
if (idleTime > IdleThreshold || isMediaPlaying)
idleMs = _cachedIdleMs;
idleTime = TimeSpan.FromMilliseconds(idleMs);
if (CurrentState == MonitorState.Resting)
{
// 用户离开了或正在播放视频
if (CurrentState == MonitorState.Working)
{
// 如果正在工作,但离开了,暂停工作计时?
// 简单起见,如果离开时间过长,可以视为一种“休息”,或者只是暂停累积
// 这里我们简单处理:如果空闲时间超过阈值,状态变为空闲
ChangeState(MonitorState.Idle);
}
// 休息模式逻辑
// 使用计数器而不是时间差,避免秒数跳变
_restElapsedSeconds++;
int totalRestSeconds = (int)RestDuration.TotalSeconds;
int remainingSeconds = totalRestSeconds - _restElapsedSeconds;
// 如果在 Idle 状态,且空闲时间非常长(比如超过了休息时间),
// 是否应该重置工作计时器?
// 假设用户去开会了1小时回来应该重新计算20分钟。
if (idleTime > RestDuration)
if (remainingSeconds <= 0)
{
_accumulatedWorkTime = TimeSpan.Zero;
}
// 如果正在播放视频,不累加工作时间,但保持当前状态
if (isMediaPlaying && CurrentState == MonitorState.Working)
{
// 保持当前剩余时间不变(不累加,也不减少)
TimeSpan remainingWork = WorkDuration - _accumulatedWorkTime;
WorkProgressChanged?.Invoke(this, remainingWork);
}
}
else
{
// 用户在活动且没有播放视频
if (CurrentState == MonitorState.Idle)
{
// 从空闲变为工作
ChangeState(MonitorState.Working);
}
// 累加工作时间
// 简单的累加逻辑:这一秒是工作的
_accumulatedWorkTime += TimeSpan.FromSeconds(1);
// 检查是否达到工作时长
TimeSpan remainingWork = WorkDuration - _accumulatedWorkTime;
if (remainingWork <= TimeSpan.Zero)
{
// 触发休息
_restElapsedSeconds = 0; // 重置休息计数器
ChangeState(MonitorState.Resting);
RestStarted?.Invoke(this, EventArgs.Empty);
// 休息结束
RestEnded?.Invoke(this, EventArgs.Empty);
ResetWork(); // 重新开始工作周期
}
else
{
WorkProgressChanged?.Invoke(this, remainingWork);
TimeSpan remainingRest = TimeSpan.FromSeconds(remainingSeconds);
RestProgressChanged?.Invoke(this, remainingRest);
}
}
else
{
// 使用缓存的媒体播放状态
bool isMediaPlaying = _cachedMediaPlaying;
// 工作/空闲模式逻辑
if (idleTime > IdleThreshold || isMediaPlaying)
{
// 用户离开了或正在播放视频
if (CurrentState == MonitorState.Working)
{
// 如果正在工作,但离开了,暂停工作计时?
// 简单起见,如果离开时间过长,可以视为一种“休息”,或者只是暂停累积
// 这里我们简单处理:如果空闲时间超过阈值,状态变为空闲
ChangeState(MonitorState.Idle);
}
// 如果在 Idle 状态,且空闲时间非常长(比如超过了休息时间),
// 是否应该重置工作计时器?
// 假设用户去开会了1小时回来应该重新计算20分钟。
if (idleTime > RestDuration)
{
_accumulatedWorkTime = TimeSpan.Zero;
}
// 如果正在播放视频,不累加工作时间,但保持当前状态
if (isMediaPlaying && CurrentState == MonitorState.Working)
{
// 保持当前剩余时间不变(不累加,也不减少)
TimeSpan remainingWork = WorkDuration - _accumulatedWorkTime;
WorkProgressChanged?.Invoke(this, remainingWork);
}
}
else
{
// 用户在活动且没有播放视频
if (CurrentState == MonitorState.Idle)
{
// 从空闲变为工作
ChangeState(MonitorState.Working);
}
// 累加工作时间
// 简单的累加逻辑:这一秒是工作的
_accumulatedWorkTime += TimeSpan.FromSeconds(1);
// 检查是否达到工作时长
TimeSpan remainingWork = WorkDuration - _accumulatedWorkTime;
if (remainingWork <= TimeSpan.Zero)
{
// 触发休息
_restElapsedSeconds = 0; // 重置休息计数器
ChangeState(MonitorState.Resting);
RestStarted?.Invoke(this, EventArgs.Empty);
}
else
{
WorkProgressChanged?.Invoke(this, remainingWork);
}
}
}
}
catch (Exception ex)
{
Logger.LogError("Error in ActivityMonitor Timer_Tick", ex);
}
}