Files
IOT_SIM/runtime/Sim.WinForms/Forms/Timer.cs
T
xuyueandClaude Opus 5.5 98be8331bc 第 0 阶段:教材项目 2 任务 1 在网页中原样运行
- runtime:仿真 WinForms 子集(Form、Button、Label、TextBox、ComboBox、
  GroupBox、Timer、MessageBox、界面线程消息循环、跨线程检查)、
  教材设备类库(DeviceCtrlHelper、LED 控件)、运行器(常驻编译服务 + 运行模式)
- server:Bun + Hono,WebSocket 会话,每次运行一个进程,消息转发
- web:Vue + Naive UI,WinForms 风格窗体渲染、MessageBox、实训台 LED 屏
- 端到端测试与 100 个程序并发的压力测试
- 教材逐任务摘要(docs/教材摘要)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 10:15:14 +08:00

79 lines
2.0 KiB
C#

using System.ComponentModel;
using Sim.Host;
namespace System.Windows.Forms;
/// <summary>窗体定时器:Tick 事件总是在界面线程上触发,上一次 Tick 处理完之前不会重复排队</summary>
public class Timer : Component
{
private System.Threading.Timer? _timer;
private int _interval = 100;
private bool _enabled;
private int _tickQueued;
public Timer() { }
public Timer(IContainer container) : this() => container.Add(this);
public int Interval
{
get => _interval;
set
{
if (value < 1) throw new ArgumentOutOfRangeException(nameof(value), $"值“{value}”对于 Interval 无效。Interval 必须大于 0。");
_interval = value;
if (_enabled) _timer?.Change(value, value);
}
}
public bool Enabled
{
get => _enabled;
set
{
if (_enabled == value) return;
_enabled = value;
if (value)
{
_timer ??= new System.Threading.Timer(_ => QueueTick());
_timer.Change(_interval, _interval);
}
else
{
_timer?.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
}
}
}
public object? Tag { get; set; }
public event EventHandler? Tick;
public void Start() => Enabled = true;
public void Stop() => Enabled = false;
protected virtual void OnTick(EventArgs e) => Tick?.Invoke(this, e);
private void QueueTick()
{
if (System.Threading.Interlocked.Exchange(ref _tickQueued, 1) == 1) return;
SimHost.Ui.Post(() =>
{
_tickQueued = 0;
if (_enabled) OnTick(EventArgs.Empty);
});
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_enabled = false;
_timer?.Dispose();
_timer = null;
}
base.Dispose(disposing);
}
}