还记得BackgroundWorker吗2014-03-20 csdn 东邪独孤打开电脑,突然想起来,昨天下午,有位仁兄和我讨论过一个事,不妨拿来说说。她说她的 牛逼程序要处理一堆东东,要弄个进度条作提示,不过进度条是在另一个窗口中的,她的想法是,在开 始处理数据时弹出进度对话框,实时显示处理进度,当处理完成后关闭对话框。乍看起来其实不难,不 过她遇到了以下问题,故在群里提问。1、模态对话框的问题。这问题好办,一般来说, 要长时间来处理数据,应该考虑后台异步操作,用砖家的话讲就是多线程。不过她在显示窗口时调用了 ShowDialog方法,这样代码会一直停在那里,直到窗口关闭。如果是异步操作,通常来说,在启 动后台任务后会马上返回,这么一来,只要把代码的顺序调一下就可以解决这问题,先启动后台任务, 再调用ShowDialog方法,这样一来,就算代码停在ShowDialog那里也不会影响后台任务的执行。2、如何控制其他窗口中控件。可以在在窗口类中定义公共方法来对控件进行某些操作, 之后在其他地方就可以通过这些公共方法来调控。如果是跨线程调用,应当考虑使用委托或事件来调用 。不然你学了委托和事件干吗呢?另一种方法就是直接把进度窗口中的ProgressBar控件声明为 public,这样其他类就可以轻松访问了。3、后台任务如何更简单。方法是灵活的,有很 多种。最简单的是利用.NET 4.5和C# 5.0 中的新特性,这种方法肯定是最简单的。第二种则是使用.NET 4 中新加的Task类来调度线程;比较传统,在2.0时代用得最多的方法是直接用Thread类。但是 ,有一个组件是专为后台任务而开放的,忘了没有?——BackgroundWorker,也许有些朋友是忘了这个 组件了。现在很多人就是这样,有了小三就忘了结发妻子,我们众多码农也是这样,常常会忘本。既有后台任务,又要报告进度,用BackgroundWorker不是更合适吗?于是我问了她两遍:“还记 得吗?” 果然不出我所料,记不起来了,呵呵。说了那么多,估计需要实例才能解决问题,好 吧,上菜。
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.IO;namespace MyApp{public partial class Form1 : Form{static string SaveDir = string.Empty;private FormProgress fpro = null;public Form1(){InitializeComponent();fpro = new FormProgress();}private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e){int fileCount = Convert.ToInt32(e.Argument);Random rand = new Random();byte[] buffer = new byte[2048];for (int i = 0; i < fileCount; i++){try{string fileName = Path.Combine(SaveDir, i.ToString() + ".tmp");using (var stream = File.Create(fileName)){int n = 0;int maxByte = 8 * 1024 * 1024;while (n < maxByte){rand.NextBytes(buffer);stream.Write(buffer, 0, buffer.Length);n += buffer.Length;}}}catch{continue;}finally{// 报告进度this.backgroundWorker1.ReportProgress(i + 1);}}}private void button1_Click(object sender, EventArgs e){if (Directory.Exists(SaveDir) == false){return;}button1.Enabled = false;int cout = Convert.ToInt32(this.nmbud.Value);this.fpro.progressBar1.Minimum = 0;this.fpro.progressBar1.Maximum = cout;this.fpro.progressBar1.Value = this.fpro.progressBar1.Minimum;this.backgroundWorker1.RunWorkerAsync(cout);// 在开始异步操作后ShowDialog// 这样即使代码停在那里也不会影响后台任务的执行fpro.ShowDialog(this);}private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e){int val = e.ProgressPercentage;this.fpro.lblText.Text = string.Format("已生成{0}个文件。", val);this.fpro.progressBar1.Value = val;}private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){button1.Enabled = true;fpro.Hide();MessageBox.Show("操作完成。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);}private void btnBrowsFd_Click(object sender, EventArgs e){FolderBrowserDialog fd = new FolderBrowserDialog();fd.RootFolder = Environment.SpecialFolder.Desktop;if (DialogResult.OK == fd.ShowDialog()){SaveDir = fd.SelectedPath;}fd.Dispose();}}}