实战.Net多线程(三)

BackgroundWorker类在 .NET Framework 2.0 中是新增的,它能够在单独的线程上执行特定操作。

关于BackgroundWorker的基本使用方法我们不在这里说明,在MSDN中已经有了很详细的介绍,并且还有个关于如何使用 BackgroundWorker 类异步执行耗时操作的示例,该示例是计算选定的斐波纳契数、在计算过程中报告进度更新,并允许取消挂起的计算等。这个例子很基础:在主窗体中有两个button,一个用于启动BackgroundWorker的执行,另一个用于取消,而进度条指示是在主窗体上显示,纵观这个示例并不是特别适用于实际使用。而我们则需要更多的功能,并且制作出接近实际使用的示例!

我们的目标有两个,1、启动和终止线程要在一个button内完成;2、需要在另一个单独的窗体中显示耗时操作的进度。解决第一个问题需要在button单击事件需要判断BackgroundWorker类的实例是否已创建,然后需要检测BackgroundWorker的一个属性IsBusy,当IsBusy=true时说明BackgroundWorker正在后台进行处理,否则可以重新开始一个后台操作,代码如下:

        private BackgroundWorker m_AsyncWorker1 = null;
        private void button4_Click(object sender, EventArgs e)
        {
            if (m_AsyncWorker1 == null)
            {
                m_AsyncWorker1 = new BackgroundWorker();
                m_AsyncWorker1.WorkerReportsProgress = true;
                m_AsyncWorker1.WorkerSupportsCancellation = true;
                m_AsyncWorker1.ProgressChanged += new ProgressChangedEventHandler(m_AsyncWorker1_ProgressChanged);
                m_AsyncWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_AsyncWorker1_RunWorkerCompleted);
                m_AsyncWorker1.DoWork += new DoWorkEventHandler(m_AsyncWorker1_DoWork);
            }
            if (m_AsyncWorker1.IsBusy)
            {
                button4.Enabled = false;
                button4.Text = "Canceling, Please wait....";
                m_AsyncWorker1.CancelAsync();
            }
            else
            {
                button4.Text = "Cancel";
                m_AsyncWorker1.RunWorkerAsync();
            }
        }

我们的示例是创建一个随机数,然后从0开始遍历这个随机数,并且通过在主窗体上的Label和ProgressBar呈现出循环的进度。

ProgressChanged、RunWorkerCompleted和DoWork是BackgroundWorker的最重要的事件,我们可以按照方法指针类型来对待它,因为其实它就是一个委托类型,为了验证DoWork是委托类型,有一个最简单方法,就是在IDE的文本编辑器中的DoWork上右键"转到定义",这时会看到DoWork是DoWorkEventHandler类型的事件,这当然没错!然后继续在DoWorkEventHandler上右键"转到定义",这时我们就会经意的发现:

public delegate void DoWorkEventHandler(object sender, DoWorkEventArgs e);

原来事件的基本形态还是委托!所以在 .Net 下事件和委托是不可分割的两种类型!!过一段时间我会特别写博文来和大家一起专门试验和探讨.Net事件和委托。

知道了是方法指针类型,我们就可以按照地址的形式赋予DoWork事件被激发时需要执行的操作的方法地址,亦即:

m_AsyncWorker1.DoWork += new DoWorkEventHandler(m_AsyncWorker1_DoWork);

好了,扯得稍微有点远了。我们继续看ProgressChanged、RunWorkerCompleted和DoWork的实际内容,代码如下:

        private void m_AsyncWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker bwAsync = sender as BackgroundWorker;
            int iCount = new Random().Next(20, 50);
            for (int i = 0; i < iCount; i++)
            {
                Thread.Sleep(100);
                bwAsync.ReportProgress(Convert.ToInt32(i * (100.0 / iCount)));
                if (bwAsync.CancellationPending)
                {
                    Thread.Sleep(1200);
                    e.Cancel = true;
                    return;
                }
            }
            bwAsync.ReportProgress(100);
        }

        private void m_AsyncWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
            label1.Text = e.ProgressPercentage.ToString() + "%";
        }

        private void m_AsyncWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            button4.Text = "Start";
            progressBar1.Value = 0;
            button4.Enabled = true;
            if (e.Error != null)
            {
                MessageBox.Show(this, e.Error.Message);
                return;
            }
            if (e.Cancelled)
            {
                //Cancelled...
            }
            else
            {
                //Completed...
            }
            m_AsyncWorker1 = null;
        }

在MSDN中关于取消后台操作的代码过于基础,不太利于实际使用。取消后台操作大家都知道需要调用m_AsyncWorker1.CancelAsync(),而在DoWork遍历数字的循环体内我们随时检测bwAsync.CancellationPending的状态,若CancellationPending=true,说明用户已经第二次单击了button,亦即执行了m_AsyncWorker1.CancelAsync() ,这是需要告知BackgroundWorker准备中止操作,即e.Cancel=true。

不管是中途取消还是顺利完成后台操作,RunWorkerCompleted事件都要最后执行,所以在这段代码中必需检测后台操作是否已取消还是顺利完成,然后添加相应的代码。

在下一篇博文中我们会继续利用BackgroundWorker来创建更加专业的在独立窗体中显示后台操作进度,以及终止后台操作的示例。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/14325734/viewspace-426849/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/14325734/viewspace-426849/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值