分别用Invoke与BackgroundWorker实现计时器

在学习.NET多线程操作的过程中,有了这个小的示例程序。

Timer

它们都使用了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

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BackgroundWorkerInvoke是两个在多线程编程中常用的概念。 BackgroundWorker是一个.NET框架中的类,用于简化多线程编程。它被设计用于在后台执行耗时的操作,以避免主线程被阻塞而导致应用程序不响应。通过BackgroundWorker,我们可以在一个分离的线程中执行任务,而不会影响到主线程的执行。它提供了事件和方法,例如DoWork事件用于执行耗时操作,ProgressChanged事件用于显示进度,RunWorkerCompleted事件用于在任务完成后执行相应的操作。通过简化多线程编程的难度,BackgroundWorker可以帮助我们更容易地实现应用程序的并发操作。 Invoke是.NET框架的一个方法,用于在多线程环境中在主线程中执行代码。由于多线程操作可能导致线程安全问题,例如跨线程操作UI组件,我们不能直接在非主线程中访问控件,否则会引发异常。在这种情况下,我们可以使用Invoke方法将代码放置在主线程中执行,以确保线程安全。Invoke方法需要一个委托作为参数,该委托指定要在主线程中执行的代码。通过在合适的时机使用Invoke,我们可以解决多线程操作时的线程安全问题。 综上所述,BackgroundWorker是一个用于分离的线程执行耗时任务的类,通过提供事件和方法简化了多线程编程的难度;而Invoke是.NET框架的一个方法,用于在多线程环境中在主线程中执行代码,以确保线程安全。两者结合使用可以更好地进行多线程编程,提高应用程序的并发性和响应性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值