试了一下BackgoundWorker,感觉用起来很不顺手,习惯了使用线程。
目标:后台计算时,在textbox里显示计算的步数,在两个progressbar里显示进度,一个progressbar在本窗体,一个在另一个窗体里。
代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; namespace 异步代理刷新控件 { public partial class Form1 : Form { //使用线程或者异步委托调用,没有区别。 private Thread thread; private delegate void InvokeDelegate(); private delegate void UpdateProgressBar(int i); private InvokeDelegate invokeDelegate; private UpdateProgressBar deleUpdateProgressBar; ProgressForm pf; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { //初始化线程 this.thread = new Thread(new ThreadStart(this.FunTest)); //初始化两个代理实例 this.invokeDelegate = new InvokeDelegate(this.FunTest); this.deleUpdateProgressBar = new UpdateProgressBar(this.SetProgress); pf = new ProgressForm(this.thread); } private void FunTest() { for (int i = 1; i < 100001; i++) { //搜索控件句柄,判断控件是否生成,不生成则返回false,此时就不能调用begininvoke方法了 //另外,如果对if内部语句的调用发生在同一线程(即UI线程或主线程),则InvokeRequired将返回false; if (this.progressBar1.InvokeRequired)//异步 { //运算(往往时后台的大量运算,不涉及控件) this.Calculation(i); //操作控件。注意参数,第二个参数是deleUpdateProgressBar所绑定的函数的所有参数 this.progressBar1.BeginInvoke(this.deleUpdateProgressBar, new object[] { i }); //一定注意,Sleep的动作一定不能放在SetTextBoxValue()方法中,因为控件的BeginInvoke()会将SetTextBoxValue()方法 //封送至后台线程,这就变成了在后台线程中让主线程Sleep300ms的时间,而不是让后台线程Sleep300ms了。 Thread.Sleep(1); } else//同步 { this.SetProgress(i); Thread.Sleep(1); } } } private void Calculation(int i) { int j = i * i;//用此代表一个大量的运算 } private void SetProgress( int i)//参数pb没有必要,可以直接调用控件,无需作为参数 { pf.progressBar1.Value = i; this.progressBar1.Value = i; this.textBox1.Text = i.ToString(); if (i == 100000) { MessageBox.Show("计算完成"); } } private void button1_Click(object sender, EventArgs e) { //this.invokeDelegate.BeginInvoke(null, null);//异步调用 //this.FunTest();//直接同步调用 //this.invokeDelegate();//同步委托调用 if (!pf.IsDisposed)//注意不要使用null判断,对象释放并不意味pf等于null { pf.Show(); } else { pf = new ProgressForm(this.thread); pf.Show(); } //线程调用 if (this.thread.IsAlive) { if (this.thread.ThreadState == ThreadState.Unstarted)//根据状态判断是否启动 { this.thread.Start(); } } else { this.thread = new Thread(new ThreadStart(this.FunTest)); this.thread.Start(); } } //这个函数代表,在做运算时,判断其他动作是否可操作 private void button2_Click(object sender, EventArgs e) { lock (this.progressBar1)//应先锁定 { if (this.progressBar1.Value < this.progressBar1.Maximum) { MessageBox.Show("正在运行,禁止介入!"); } else { MessageBox.Show("计算完毕,可以介入!"); } } } private void button3_Click(object sender, EventArgs e) { //函数过时 this.thread.Suspend(); } private void button4_Click(object sender, EventArgs e) { if (this.thread.ThreadState == ThreadState.Suspended) { this.thread.Resume(); } } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { this.thread.Abort();//窗体关闭时,必须销毁线程,如果在线程运行时关闭窗体,该线程仍在计算中 } } }
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; namespace 异步代理刷新控件 { public partial class ProgressForm : Form { public ProgressForm() { InitializeComponent(); } public Thread thread; public ProgressForm(Thread t) { InitializeComponent(); this.thread = t; } } }