很多情况下,我们在处理大数据时需要使用进度条,尤其是以模式窗口打开的进度条。
使用以模式窗口打开的进度条有两个好处。
第一,可以增加用户友好性。
第二,可以防止用户在等待时间多次点击页面按钮。
先说一下主要实现思想:
都知道如果在主窗体打开任何一个模式窗口时,当前窗体的进程将停止,知道模式窗口关闭为止,
这时如何才能突破这个一成不变的定律呢?
哈哈猜对了,就是它!使用线程~~~~
我们可以使用一个线程在主窗体上打开一个模式窗口,而且这个模式窗口还不会影响主窗体的线性执行逻辑!
下面就是代码实现了:
//1 建立一个有进度条(pbar 为进度条控件的名字)的Form窗体,并外公布几个进度条的必要属性
#region 属性 /// <summary> /// 设置进度条的最小值(默认1) /// </summary> public int ProgersMinimum { set { pbar.Minimum = value; } get { return pbar.Minimum; } } /// <summary> /// 设置进度条的最最大值(默认100) /// </summary> public int ProgersMaximum { set { pbar.Maximum = value; } get { return pbar.Maximum; } } /// <summary> /// 设置进度条的当前值(默认1) /// </summary> public int ProgersValue { set { pbar.Value = value; } get { return pbar.Value; } } /// <summary> /// 设置进度条的步长大值(默认1) /// </summary> public int ProgersStep { set { pbar.Step = value; } get { return pbar.Step; } } #endregion
#region 方法
/// <summary> /// 增加进度 /// </summary> /// <param name="value">需要增加的值</param> /// <returns></returns> public bool Increase(int value) { if (!this.IsHandleCreated) return false; //关闭进度条窗口 Action WinClose=(()=>{ this.Close(); });
//设置当前进度条位置 Action<int> SetProgresValue = ((val) => { if (val < 0 || val > pbar.Maximum || val < pbar.Minimum) { pbar.Value = pbar.Maximum; this.Close(); return; }
pbar.Value = val; });
try { this.Invoke(SetProgresValue, value); } catch { }
return !(value < 0 || value > pbar.Maximum || value < pbar.Minimum); }
#endregion
//2.接下来就是在主窗体中的逻辑了
//2.1 声明 3 个类的成员变量
/// <summary> /// 进度条窗体 /// </summary> private CommonFrm.FrmProgres m_frmProgres = null; /// <summary> /// 控制进度条进度的代理 /// </summary> /// <returns></returns> private delegate bool DelIncreaseHandle(int value); /// <summary> /// 控制进度条进度的代理变量 /// </summary> private DelIncreaseHandle m_ctrlProgresIncrease = null;
//2.2 编写一个打开进度条窗体的方法,如果要使用进度条时调一下就 OK 了
/// <summary> /// 显示进度条 /// </summary> /// <param name="maxiNum">进度条最大值</param> /// <param name="miniNum">进度条最小值</param> private void ShowProgress(int miniNum,int maxiNum) { Thread thread = null; //1 打开进度条窗体 Action showDialogProgress = (() => { m_frmProgres = new CommonFrm.FrmProgres(); m_frmProgres.FormClosed += delegate(object sender, FormClosedEventArgs e) {
//添加这行代码会引发异常 //if (null != thread) //如果进度条界面关闭了,就终止打开窗体的进程 // thread.Abort(); }; m_ctrlProgresIncrease = new DelIncreaseHandle(m_frmProgres.Increase); m_frmProgres.ProgersMinimum = miniNum; //设置进度条的最小值 m_frmProgres.ProgersMaximum = maxiNum;//设置进度条的最大值 m_frmProgres.StartPosition = FormStartPosition.CenterScreen; //进度条窗体打开的位置 m_frmProgres.ShowDialog(); //以模式状态打开进度条窗体
m_ctrlProgresIncrease = null; m_frmProgres = null; });
//2 启动线程 thread = new Thread(new ThreadStart(showDialogProgress)); thread.IsBackground = false; // 测试的时候这个东西似乎有点儿影响,没搞明白具体意思呢! thread.Start(); /* * 使线程睡眠一会儿,给窗口展现预留时间 * 窗体不展现前 m_ctrlProgresIncrease 为 null * 将导致使用 this.Invoke 调用 m_ctrlProgresIncrease 委托时页面无限等待 */ Thread.Sleep(1000); }
// 接下来就是 调用了!!!!!!
/// <summary> /// 测试 /// </summary> private void btnTest_Click(object sender, EventArgs e) {
int miniMun = 0; int maxiNum = 100; this.ShowProgress(miniMun, maxiNum); // 打开模式进度条窗口 for (int i = miniMun; i <= maxiNum; i++) { if(null != m_ctrlProgresIncrease) this.BeginInvoke(m_ctrlProgresIncrease, i); // 设置进度条的值
Thread.Sleep(10); } if (null != m_ctrlProgresIncrease) this.BeginInvoke(m_ctrlProgresIncrease, -1); }
--------------------------------------
注意:上面用到了 this.BeginInvoke 和 this.Invoke
this.BeginInvoke :不需要等待调用的方法执行完毕
this.Invoke :需要等待调用的方法执行完毕
--------------------------------------
功能到此结束了!不过还不够灵活,如果在多个页面用还是要将 代码拷贝 过去。
转载于:https://www.cnblogs.com/xxj-jing/archive/2012/03/08/2890082.html
相关资源:各显卡算力对照表!