1.System.Windows.Forms.Timer
直接从 Toolbox 中拖拽 Timer 控件到 Form 上,设置其属性及 Tick 事件,
private void Form1_Load(object sender, EventArgs e) { timer1.Enabled = true; timer1.Interval = 1000; // ms MainBox.Text = Thread.CurrentThread.ManagedThreadId.ToString(); } int count = 0; private void timer1_Tick(object sender, EventArgs e) { count++; label1.Text = count.ToString() + "s"; MethodBox.Text = Thread.CurrentThread.ManagedThreadId.ToString(); }
System.Windows.Forms.Timer 中的频率不准确,且和 UI 处于同一线程,易造成假死,但较为方便。
2.System.Timers.Timer
public Form1() { InitializeComponent(); Control.CheckForIllegalCrossThreadCalls = false; // 关闭与UI线程交互的保护机制
// 或者设置Timer.SynchronizingObject Property属性
MainBox.Text = Thread.CurrentThread.ManagedThreadId.ToString(); } private System.Timers.Timer myTimer; int count = 0; private void Form1_Load(object sender, EventArgs e) { //窗体打开时创建定时器,并设置执行频率时间 this.myTimer = new System.Timers.Timer(1000); //设置任务 this.myTimer.Elapsed += new System.Timers.ElapsedEventHandler(myTimer_Elapsed); this.myTimer.AutoReset = true; this.myTimer.Enabled = true; this.myTimer.Start(); } private void myTimer_Elapsed(object sender, ElapsedEventArgs e) { count++; label1.Text = count.ToString() + "s"; MethodBox.Text = Thread.CurrentThread.ManagedThreadId.ToString(); }
System.Timers.timer 先访问线程池,若线程池中的线程都忙碌,则会创建一个新的线程执行,所以不存在假死,频率比较准确,但由于不同于 UI 线程,无法直接交互,只能关闭安全机制(不建议)或通过委托(Invoke 和 BeginInvoke)实现跨线程访问 UI。
若在“myTimer_Elapsed”中模拟耗时方法,则 MethodThreadId 并不是固定不变的。