方法一:使用线程
功能描述:在用c#做WinFrom开发的过程中。我们经常需要用到进度条(ProgressBar)用于显示进度信息。这时候我们可能就需要用到多线程,如果不采用多线程控制进度条,窗口很容易假死(无法适时看到进度信息)。下面我就简单结合一个我写的例子给大家做一个介绍。
第一步:设计界面,注意需要引用 using System.Threading;
控件名称分别为:
progressBar1;label1;textBox1;button1;
第二步:定义一个代理,用于更新ProgressBar的值(Value)及在执行方法的时候,返回方法的处理信息。
private delegate void SetPos(int ipos,string vinfo);//代理
第三步:进度条值更新函数(参数必须跟声明的代理参数一样)
private void SetTextMesssage(int ipos,string vinfo) { if (this.InvokeRequired) { SetPos setpos = new SetPos(SetTextMesssage); this.Invoke(setpos, new object[] { ipos,vinfo }); } else { this.label1.Text = ipos.ToString() + "/1000"; this.progressBar1.Value = Convert.ToInt32(ipos); this.textBox1.AppendText(vinfo); } }
第四步:函数实现
private void button1_Click(object sender, EventArgs e) { Thread fThread = new Thread(new ThreadStart(SleepT)); fThread.Start(); }
第五步:新的线程执行函数:
private void SleepT() { for (int i = 0; i < 500; i++) { System.Threading.Thread.Sleep(10); SetTextMesssage(100*i/500,i.ToString()+" "); } }
程序运行效果图:
方法二:控件BackgroundWorker
功能描述:该种方法通过控件backgroundWorker1实现,进度条。进度条在一个模板窗体内。
第一步:主窗体设计:
控件名称:button1;backgroundWorker1;对backgroundWorker1控件,属性设置。
第二步:主页面后台代码:
using System.Threading;//引用空间名称 private void button1_Click(object sender, EventArgs e) { this.backgroundWorker1.RunWorkerAsync(); // 运行 backgroundWorker 组件 ProcessForm form = new ProcessForm(this.backgroundWorker1);// 显示进度条窗体 form.ShowDialog(this); form.Close(); } private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Error != null) { MessageBox.Show(e.Error.Message); } else if (e.Cancelled) { } else { } } //你可以在这个方法内,实现你的调用,方法等。 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = sender as BackgroundWorker; for (int i = 0; i < 100; i++) { Thread.Sleep(100); worker.ReportProgress(i); if (worker.CancellationPending) // 如果用户取消则跳出处理数据代码 { e.Cancel = true; break; } } }
分别为button控件和backgroundWorker1控件选好事件。
第三步:设置子窗体(及显示进度条的窗体):
控件名称:
progressBar1;button1
第四步:子窗体,后台代码:
private BackgroundWorker backgroundWorker1; //ProcessForm 窗体事件(进度条窗体) public ProcessForm(BackgroundWorker backgroundWorker1) { InitializeComponent(); this.backgroundWorker1 = backgroundWorker1; this.backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged); this.backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted); } void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { //this.Close();//执行完之后,直接关闭页面 } void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { this.progressBar1.Value = e.ProgressPercentage; } private void button1_Click(object sender, EventArgs e) { this.backgroundWorker1.CancelAsync(); this.button1.Enabled = false; this.Close(); }
只为button选好事件,执行效果为:
方法三:方法二增强
功能描述:在处理大量数据的时候,有时候方法的执行需要一定的时间,这时候往往会造成页面或程序的“假死”状态,给用户的体验度也不是很好。为了避免出现“假死”提高用户的体验度,在这里为这类型的方法加了一个进度条和一个文本框,进度条用于显示程序处理的进度,文本框用于显示在处理过程中,给与的提示。本方法主要使用了控件:backgroundWorker1;说明:本方法与上面的方法(方法二)基本类型,主要是设计和代码进行了一些修改。
第一步:主窗体设计:
控件名称:button1;backgroundWorker1;对backgroundWorker1控件,属性设置。
第二步:主窗体 后台代码:
private void button1_Click(object sender, EventArgs e) { this.backgroundWorker1.RunWorkerAsync(); // 运行 backgroundWorker 组件 ProcessForm form = new ProcessForm(this.backgroundWorker1);// 显示进度条窗体 form.ShowDialog(this); form.Close(); } private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Error != null) { MessageBox.Show(e.Error.Message); } else if (e.Cancelled) { } else { } } //你可以在这个方法内,实现你的调用,方法等。 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = sender as BackgroundWorker; for (int i = 0; i < 100; i++) { Thread.Sleep(100); worker.ReportProgress(i, i.ToString() + " 你好! "); //注意:这里向子窗体返回信息值,这里是两个值,一个用于进度条,一个用于文本框的。 if (worker.CancellationPending) // 如果用户取消则跳出处理数据代码 { e.Cancel = true; break; } } }
第三步:设置子窗体(及显示进度条的窗体):
控件:progressBar1;textBox1;button1
第四步:子窗体后台代码:
private BackgroundWorker backgroundWorker1; //ProcessForm 窗体事件(进度条窗体) public ProcessForm(BackgroundWorker backgroundWorker1) { InitializeComponent(); this.backgroundWorker1 = backgroundWorker1; this.backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged); this.backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted); } void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { //this.Close();//执行完之后,直接关闭页面 } void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { this.progressBar1.Value = e.ProgressPercentage; this.textBox1.AppendText(e.UserState.ToString());//主窗体传过来的值,通过e.UserState.ToString()来接受 } private void button1_Click(object sender, EventArgs e) { this.backgroundWorker1.CancelAsync(); this.button1.Enabled = false; this.Close(); }
实现的效果:
注意:如果在程序为执行完,就点击取消的话,很有可能会报错的,这时候,你就修改一个方法:backgroundWorker1_ProgressChanged如下:
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { this.progressBar1.Value = e.ProgressPercentage; this.textBox1.Text += e.UserState.ToString(); //主窗体传过来的值,通过e.UserState.ToString()来接受 }
把这个方法,替换上边的那个方法,就可以了。
方法四:线程与代理
功能描述:本方法实现进度条显示,方法执行信息反馈显示。用到的技术点为 线程与代理。
步骤一:添加主页面。
控件名称:button1;
步骤二:主页面后台代码
using System.Threading;//引用此命名 //创建代理。 private Form6 myProcessBar = null;//弹出的子窗体(用于显示进度条) private delegate bool IncreaseHandle(int nValue,string vinfo);//代理创建 private IncreaseHandle myIncrease = null;//声明代理,用于后面的实例化代理 private int vMax = 100;//用于实例化进度条,可以根据自己的需要,自己改变 private void button1_Click(object sender, EventArgs e) { Thread thdSub = new Thread(new ThreadStart(ThreadFun)); thdSub.Start(); } private void ThreadFun() { MethodInvoker mi = new MethodInvoker(ShowProcessBar); this.BeginInvoke(mi); Thread.Sleep(100); object objReturn = null; for (int i = 0; i < vMax; i++) { objReturn = this.Invoke(this.myIncrease, new object[] { 2, i.ToString() + " " }); Thread.Sleep(50); } } private void ShowProcessBar() { myProcessBar = new Form6(vMax); myIncrease = new IncreaseHandle(myProcessBar.Increase); myProcessBar.ShowDialog(); myProcessBar = null; }
步骤三:创建子窗体
控件名称:progressBar1;textBox1
步骤四:子窗体,后台代码
public Form6(int vMax) { InitializeComponent(); this.progressBar1.Maximum = vMax; } public bool Increase(int nValue,string nInfo) { if (nValue > 0) { if (progressBar1.Value + nValue < progressBar1.Maximum) { progressBar1.Value += nValue; this.textBox1.AppendText(nInfo); Application.DoEvents(); progressBar1.Update(); progressBar1.Refresh(); this.textBox1.Update(); this.textBox1.Refresh(); return true; } else { progressBar1.Value = progressBar1.Maximum; this.textBox1.AppendText(nInfo); //this.Close();//执行完之后,自动关闭子窗体 return false; } } return false; }