天天看点

C#编程---进度条显示处理进度

 本文介绍如何在处理事务时使用进度条显示处理进度。

    上下文背景:Form1类处理(模拟批量导入)产生会员信息数组。调用导入管理器ImportMgr类Work函数,实现批量导入会员信息,导入时显示导入进度,导入完成后将会员信息显示到列表listBox1。导入管理器ImportMgr类调用信息处理类ProcessInfo进行导入数据操作,调用进度条状态窗口类frmstatus显示导入进度。当导入数据完成时广播导入数据完成事件ImportDone。信息处理类ProcessInfo使用线程函数ImportMemberThreadFun开启实际导入数据函数ImportMember导入数据。在ImportMember函数中,每导入一条数据,会广播一次更新进度事件UpdateProgressValue。导入数据完成即广播导入数据完成事件ImportDone。下面简要介绍各个类。

    首先介绍需要用到的参数结构体:

    [数据结构.cs]

using System;

/// <summary>
/// 导入数据线程的参数
/// </summary>
public struct ImportParameter
{
    /// <summary>
    /// 会员名称数组
    /// </summary>
    public string[] MemberNames;
}


/// <summary>
/// 处理进度数值参数
/// </summary>
public class ProcessEventArgs : EventArgs
{
    /// <summary>
    /// 进度数值
    /// </summary>
    public int Value;
}

/// <summary>
/// (导入数据完成时的用到的)数据参数
/// </summary>
public class ImportEventArgs : EventArgs
{
    /// <summary>
    /// 数据数组
    /// </summary>
    public string[] datas;
}


           

    ImportaParameter是批量导入线程用到的数据参数。ProgressBarEventArgs是进度变更事件的数值参数。ImportEventArgs是导入数据完成事件用到的数据参数。

然后是主窗体类[

Form1.cs]

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Threading;

namespace 进度条显示处理进度
{
    public partial class Form1 : Form
    {
        #region 本地变量

        /// <summary>
        /// 导入管理器实例
        /// </summary>
        ImportMgr mgr;
        #endregion

        #region 构造函数

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            mgr = new ImportMgr();    
            //绑定导入数据操作完成要执行的函数
                       mgr.ImportDone+=new EventHandler<ImportEventArgs>(Mgr_ImportDone);
        }
        #endregion

        #region 功能函数

        //导入管理器导入操作完成后调用的函数
        private void Mgr_ImportDone(object sender, EventArgs e)
        {
            //参数类型转换
            ImportEventArgs ie = (ImportEventArgs)e;
            //加载数据到控件
            this.ListBoxAddDatas(ie.datas);

        }

        //测试1
        private void F测试1()
        {
            ImportParameter para = new ImportParameter();//传入到线程内的参数
            
            //假定有100名会员
            para.MemberNames = new string[100];
            
            for (int i = 0; i < 100; i++)
            {
                para.MemberNames[i] = "机器人"+(i+1).ToString();
            }

            mgr.Work(para);//导入管理器开始工作:导入会员数据
        }
        
        //加载数据到控件的委托
        public delegate void AddDatasDelegate(string[] datas);


        //加载数据到控件
        public void ListBoxAddDatas(string[] datas)
        {
            //外部线程加载数据的操作请求
            if (listBox1.InvokeRequired)
            {
                AddDatasDelegate d = new AddDatasDelegate(ListBoxAddDatas);
                listBox1.Invoke(d, new object[] { datas });
            }
            else //(本线程内)控件加载数据
            {
                this.AddDatas(datas);
            }

        }
        //(本线程内)控件加载数据
        private void AddDatas(string[] datas)
        {
            foreach (string t in datas)
            {
                this.listBox1.Items.Add(t);
            }
        }


        #endregion

        #region 事件响应

        private void btn_测试_Click(object sender, EventArgs e)
        {
            this.F测试1();
        }

        #endregion

        

    }
}
           

    然后是处理信息的类

    [ProcessInfo.cs]

using System;
using System.Collections.Generic;
using System.Text;

using System.Threading;

namespace 进度条显示处理进度
{
    /// <summary>
    /// 处理信息类
    /// </summary>
    public class ProcessInfo
    {
        public ProcessInfo()
        { 
            
        }
        
        #region 处理信息--业务逻辑端

        /// <summary>
        /// 更新进度信息事件
        /// </summary>
        public event EventHandler<ProcessEventArgs> UpdateProgressValue;
        
        /// <summary>
        /// 导入数据完成事件
        /// </summary>
        public event EventHandler<ImportEventArgs> ImportDone;
       
        /// <summary>
        /// 线程函数(此例中线程操作为为导入会员)
        /// </summary>
        /// <param name="msg">会员信息集</param>
        public void ImportMemberThreadFun(object msg)
        {
            Thread importMemberThread = new Thread(new ParameterizedThreadStart(ImportMember));
            importMemberThread.Start(msg);
        }
        /// <summary>  
        /// 线程实际操作函数(导入会员信息)
        /// </summary>  
        private void ImportMember(object msg)
        {
            ImportParameter para = (ImportParameter)msg;//线程参数:所导入会员数据
            ImportEventArgs importDatas = new ImportEventArgs();
            double t=0;
            try
            {
                importDatas.datas = new string[para.MemberNames.Length];
                for (int i = 0; i < para.MemberNames.Length; i++)
                {
                							//处理进度数值参数
                    ProcessEventArgs pe = new ProcessEventArgs();

                    t = 100 * (i + 1) / para.MemberNames.Length;//算出处理进度

                    pe.Value = (int)Math.Floor(t);//进度值向下取整

                    importDatas.datas[i] = para.MemberNames[i];//在此就算导入数据了(模拟)
                    this.UpdateProgressValue(this, pe);				//更新进度
                    
                    Thread.Sleep(50);	//模拟导入数据耗时
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            //广播导入完成事件
            this.ImportDone(this, importDatas);

        }

        #endregion
       
    }
}
           

    UpdateProgressValue是变更进度信息事件,ImportMemberThreadFun是线程函数,ImportMember是线程函数调用的实际处理信息的函数,该函数每处理完一条信息都会触发一次。

    然后是进度条状态窗体

    [frmstatus.cs]

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace 进度条显示处理进度
{
    public partial class frmStatus : Form
    {
        /// <summary>
        /// 进度完成进度完成
        /// </summary>
        private bool workDone = false;

        /// <summary>
        /// 显示信息
        /// </summary>
        public string Message = string.Empty;

        //构造函数
        public frmStatus()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 设置进度条进度值委托
        /// </summary>
        /// <param name="value">进度值</param>
        public delegate void SetProgressValueDelegate(int value);

        /// <summary>
        /// (创建本控件的线程)设置进度条数值
        /// </summary>
        /// <param name="value">进度条数值</param>
        private void SetValue(int value)
        {
            this.progressBar1.Value = value;
            this.lblStatus.Text = this.Message 
                + Environment.NewLine 
                + Environment.NewLine 
                + "        进度 :" + value.ToString() + "%";

            if (value == this.progressBar1.Maximum)
            {
                this.Message = "        操作已完成!";
                this.lblStatus.Text = this.Message
                    + Environment.NewLine + Environment.NewLine 
                    + "        进度 :" + value.ToString() + "%";

                workDone = true;
                
            }

            if (workDone)
            {
                this.btn_close.Visible = true;
            }
        }

        //设置进度条进度值
        /// <summary>
        /// 设置进度条进度值
        /// </summary>
        /// <param name="value">进度值</param>
        public void SetProgressValue(int value)
        {
            //外部线程设定进度值的操作请求
            if (this.InvokeRequired)
            {
                SetProgressValueDelegate d = new SetProgressValueDelegate(SetProgressValue);
                this.Invoke(d, new object[] { value });
            }
            else //(本线程内)设定进度值
            {
                this.SetValue(value);
            }
            
        }

        private void btn_close_Click(object sender, EventArgs e)
        {
            this.Visible = false;
        }

    }
}
           

    SetProgressValue是外部请求设置进度值的函数,SetValue是创建本控件类内部实际设置进度值的函数。SetProgressValueDelegate是设置进度条进度值委托。

    然后是导入管理器

    [ImportMgr.cs]

using System;
using System.Collections.Generic;
using System.Text;

namespace 进度条显示处理进度
{
   
    /// <summary>
    /// 导入管理器
    /// </summary>
    public class ImportMgr
    {
        /// <summary>
        /// 进度条状态窗口
        /// </summary>
        frmStatus frmStatusMessage;

        /// <summary>
        /// 导入数据完成事件
        /// </summary>
        public event EventHandler<ImportEventArgs> ImportDone;
       
        /// <summary>
        /// 处理信息对象
        /// </summary>
        ProcessInfo processer;

        string[] nameDatas;

        public ImportMgr()
        {
            frmStatusMessage = new frmStatus();//初始化状态窗口
            processer = new ProcessInfo();//初始化处理信息对象

            //订阅处理信息状态事件        
            processer.UpdateProgressValue += new EventHandler<ProcessEventArgs>(ImportMgr_UpdateProgressValue);

            //绑定导入数据操作完成要执行的函数
            processer.ImportDone +=new EventHandler<ImportEventArgs>(Processer_ImportDone);

        }

        //更新进度信息事件,processer.UpdateProgressValue每广播一次就调用此函数
        private void ImportMgr_UpdateProgressValue(object sender, EventArgs e)
        {
            ProcessEventArgs se = (ProcessEventArgs)e;
            frmStatusMessage.SetProgressValue(se.Value);//请求设定进度值
        }
      
        //广播导入数据完成事件(并传出所导入的数据)
        private void Processer_ImportDone(object sender, EventArgs e)
        {
            ImportEventArgs ie = (ImportEventArgs)e;
            nameDatas = ie.datas; ;
            this.ImportDone(this, ie);

        }

        /// <summary>
        /// 工作:导入会员数据
        /// </summary>
        /// <param name="p">参数:会员数据</param>
        public void Work(ImportParameter p)
        {            
            processer.ImportMemberThreadFun(p);//调用启动线程函数,导入会员名称数据
            frmStatusMessage.Show();//显示进度条窗口
        }
    }
}
           

    导入管理器包含了进度条显示窗口frmStatusMessage、处理信息对象processer。成员函数Work即导入操作的实际工作函数。导入管理器导入完数据会广播导入数据完成事件ImportDone。

继续阅读