在学习.NET多线程操作的过程中,有了这个小的示例程序。
它们都使用了System.Timers.Timer作为计时器,只是在更新UI时分别使用了传统的Invoke方式与.NET 4.0后引入的BackgroundWorker。从个人感受而言,前者少许多编码,后者从逻辑上更易理解。
源代码下载(7zip压缩)
一、传统Invoke方式
#region implementation by Invoke() private System.Timers.Timer _timer = new System.Timers.Timer(1000); private bool IsInvokeRunning = false; private int _secondsOfInvoke = 0; private void InitializeTimer() { _timer.AutoReset = true; _timer.Elapsed += new System.Timers.ElapsedEventHandler( (ts, te) => { _secondsOfInvoke++; string message = new TimeSpan(0, 0, _secondsOfInvoke).ToString(@"mm\:ss"); SetLabelText(message); } ); } private void btnBegin_Click(object sender, EventArgs e) { if (IsInvokeRunning) { IsInvokeRunning = false; _timer.Stop(); string message = string.Format("{0} past.", new TimeSpan(0, 0, _secondsOfInvoke).ToString(@"mm\:ss")); MessageBox.Show(message); this.btnBegin.Text = "Begin"; _secondsOfInvoke = 0; this.labelInvokeTime.Text = "00:00"; } else { IsInvokeRunning = true; _timer.Start(); this.btnBegin.Text = "Cancel"; } } private delegate void SetLabelTextHandler(string text); private void SetLabelText(string text) { if (this.labelInvokeTime.InvokeRequired) { SetLabelTextHandler handler = new SetLabelTextHandler(SetLabelText); this.Invoke(handler, new object[] { text }); } else this.labelInvokeTime.Text = text; } #endregion
二、BackgroundWorker方式
#region implementation by BackgroundWorker private BackgroundWorker _worker = new BackgroundWorker() { WorkerSupportsCancellation = true, WorkerReportsProgress = true }; private bool IsWorkerRunning = false; private int _secondsOfWorker = 0; private void InitializeWorker() { _worker.DoWork += new DoWorkEventHandler( (s, e) => { System.Timers.Timer timer = new System.Timers.Timer(1000); timer.AutoReset = true; timer.Elapsed += new System.Timers.ElapsedEventHandler( (ts, te) => { _secondsOfWorker++; _worker.ReportProgress(0); }); timer.Start(); while (true) { if (_worker.CancellationPending) { e.Cancel = true; timer.Stop(); return; } } }); _worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler( (s, e) => { if (e.Cancelled) { IsWorkerRunning = false; this.btnStart.Text = "Start"; } string message = string.Format("{0} past.", new TimeSpan(0, 0, _secondsOfWorker).ToString(@"mm\:ss")); MessageBox.Show(message); _secondsOfWorker = 0; this.labelWorkerTime.Text = "00:00"; }); _worker.ProgressChanged += new ProgressChangedEventHandler( (s, e) => { string message = new TimeSpan(0, 0, _secondsOfWorker).ToString(@"mm\:ss"); this.labelWorkerTime.Text = message; }); } private void btnStart_Click(object sender, EventArgs e) { if (IsWorkerRunning) { IsWorkerRunning = false; this.btnStart.Text = "Start"; _worker.CancelAsync(); } else { IsWorkerRunning = true; this.btnStart.Text = "Stop"; _worker.RunWorkerAsync(); } } #endregion