BackgroundWorker 实现多线程操作

前端之家收集整理的这篇文章主要介绍了BackgroundWorker 实现多线程操作前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

背景介绍:

           在做程序的进程中,我们极可能遇到这样的情况:当我们履行1个比较耗时的操作,即界面加载数据量略大的时,在该操作未完成之前再去操作界面,就会出现停止响应的情况,这称为界面假死状态,那1个小圆圈转呀转的,想必大家看着就头疼。固然这是1个非常影响用户体验度的地方。

       怎样做出1个能够及时响应的用户界面呢?多线程操作。

       引入BackgroundWorker组件:

       BackgroundWorker是・net里用来履行多线程任务的控件,它允许编程者在1个单独的线程上履行1些操作。

经常使用方法@H_404_27@

1.RunWorkerAsync 开始履行后台操作。引发 DoWork 事件@H_404_27@

2.CancelAsync 要求取消挂起的后台操作。@H_404_27@

        注意:这个方法是将 CancellationPending 属性设置为 true,其实不会终止后台操作。在后台操作中要检查 CancellationPending 属性,来决定是不是要继续履行耗时的操作。@H_404_27@

 3.ReportProgress 引发 ProgressChanged 事件。@H_404_27@

经常使用属性@H_404_27@

1.CancellationPending 唆使利用程序是不是已要求取消后台操作。只读属性,默许为 false,当履行了 CancelAsync 方法后,值为 true。@H_404_27@

 2.WorkerSupportsCancellation 唆使是不是支持异步取消。要履行 CancelAsync 方法,需要先设置该属性为 true。@H_404_27@

 3.WorkerReportsProgress 唆使是不是能报告进度。要履行 ReportProgress 方法,需要先设置该属性为 true。@H_404_27@

经常使用事件@H_404_27@

 1.DoWork 调用 RunWorkerAsync 方法时产生。@H_404_27@

 2.RunWorkerCompleted 后台操作已完成、被取消或引发异常时产生。@H_404_27@

 3.ProgressChanged 调用 ReportProgress 方法时产生。@H_404_27@

         注意:在 DoWork 事件处理程序中不操作任何用户界面对象。而应当通过 ProgressChanged 和RunWorkerCompleted 事件与用户界面进行通讯。

         如果想在 DoWork 事件处理程序中和用户界面的控件通讯,可在用 ReportProgress 方法。ReportProgress(int percentProgress,object userState),可以传递1个对象。

         ProgressChanged 事件可以从参数ProgressChangedEventArgs 类的UserState 属性得到这个信息对象。这个事件也能够实现进度条功能,把任务的进度实时显现给用户

 

       简单的程序用BackgroundWorker 比 Thread 方便,Thread中和用户界面上的控件通讯比较麻烦,需要用拜托来调用控件的 Invoke 或BeginInvoke 方法,没有 BackgroundWorker 方便。

 

BackgroundWorker Demo

namespace BackgroundWorkerTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); backgroundWorker1.WorkerReportsProgress = true;//报告完成进度 backgroundWorker1.WorkerSupportsCancellation = true;//允许用户终止后台线程 } //开始按钮 private void button1_Click(object sender,EventArgs e) { if (!backgroundWorker1.IsBusy )//判断backgroundWorker1是不是正在运行异步操作 { //backgroundWorker1.RunWorkerAsync(); backgroundWorker1.RunWorkerAsync(1000);//开始履行后台操作,调用DoWork事件 } } //DoWork事件声明要履行的耗时操作 private void backgroundWorker1_DoWork(object sender,DoWorkEventArgs e) { e.Result = ListNumber(backgroundWorker1,e);//运算结果保存在e.Result中 } bool ListNumber(object sender,DoWorkEventArgs e) { int num=(int)e.Argument;//接收传入的参数 for (int i = 1; i <= num; i++) { if (backgroundWorker1.CancellationPending)//判断是不是要求了取消后台操作 { e.Cancel=true; return false; } //backgroundWorker1.ReportProgress(i * 100 / num); backgroundWorker1.ReportProgress(i * 100 / num,i);//报告完成进度 Thread.Sleep(0);//后台线程交出时间片 } return true; } private void backgroundWorker1_ProgressChanged(object sender,ProgressChangedEventArgs e) { //将完成进度数据传给进度条 progressBar1.Value = e.ProgressPercentage; label1.Text = e.ProgressPercentage + "%"; //将中间计算结果在ListBox控件中显示出来 listBox1.Items.Add(e.UserState); } Private void backgroundWorker1_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e) { if (!e.Cancelled && e.Error==null) { MessageBox.Show("处理完成了吗? " + e.Result); } else//如果取消后台线程或产生了异常 { MessageBox.Show("处理完成了吗? false"); } } //取消按钮 private void button2_Click(object sender,EventArgs e) { if (backgroundWorker1.WorkerSupportsCancellation==true) { backgroundWorker1.CancelAsync();//取消后台操作 backgroundWorker1.Dispose();//释放资源 } } } }

总结:

使用backgroundWorker实现多线程大致的步骤是:

1 绑定线程,设置属性

2调用BackgroundWorkerRunWorkerAsync方法(可以传递参数),它将调用DoWork事件

3、声明DoWork事件的拜托方法,在后台履行耗时的操作

4、在耗时操作中判断CancellationPending属性,如果为false退出

5、如果要向用户界面发送信息,则调用BackgroundWorkerReportProgress方法,它将调用ProgressChanged事件(可以将改变通过object类型传递)

6、在ProgressChanged事件的响应代码中将改变显现给用户,类似进度条。

7、如果需要取消耗时操作,则调用BackgroundWorkerCancelAsync方法,需要和步骤31起使用

 

    总的来讲就是用backgroundWorker组件来新建1个线程,把耗时的部份放到这个线程中在后台进行处理。这样就不会影响界面的正常使用。举个通俗的例子,在我们打开1个网页的时候,先加载完的总是文字,然后图片在渐渐出现。这就是线程的利用,网页打开的时候先显现出文字,供用户阅读,然后把加载图片放到1个单独的线程中,异步的在后台履行,履行终了后把图片显现出来。

    这样就避免了1打开界面就加载大量信息,而酿成的界面假死状态,大大提高了用户体验度。

 

 

线程处理这块不熟,希望大家指导。


猜你在找的PHP相关文章