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