分别用Invoke与BackgroundWorker实现计时器
程序员文章站
2022-06-10 11:07:38
...
在学习.NET多线程操作的过程中,有了这个小的示例程序。
它们都使用了System.Timers.Timer作为计时器,只是在更新UI时分别使用了传统的Invoke方式与.NET 4.0后引入的BackgroundWorker。从个人感受而言,前者少许多编码,后者从逻辑上更易理解。
一、传统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