zoukankan      html  css  js  c++  java
  • 对进度条的通用封装实现

              一直想写点啥对最近的工作做个总结,由于项目比较忙,可能还有自己的各种理由推脱有点懈怠,零碎的总结过一些,都没有动笔写下来过。眼看2013都要过去了,该写点啥来总结下。先从自己对进度封装的一点学习经验写出来,供大家交流,欢迎园子里的朋友不吝啬的拍砖。

             首先定义对进度表示的契约,定义进度行为(IProgressor)、进度信息(IStepProgress)和中断处理(ITrackCancel)的接口如下:

        /// <summary>
        /// 进度行为接口
        /// </summary>
        public interface IProgressor
        {
            string Message { get; set; }
            void Show();
            void Hide();
            void Step();
        }
         /// <summary>
        /// 进度展示接口
        /// </summary>
        public interface IStepProgress : IProgressor
        {
            int MaxRange { get; set; }
            int MinRange { get; set; }
            int StepValue { get; set; }
            i
        /// <summary>
        /// 中断接口
        /// </summary>
        public interface ITrackCancel
        {
            void Cancel();
            bool Continue();
            bool CancelOnClick { get; set; }
            bool CancelOnKeyPress { get; set; }
    
            IProgressor Progressor { get; set; }
        }

              实现进度信息接口,实现类(ProgressBarDialog)如下:

        /// <summary>
        /// 进度实现类
        /// </summary>
        public class ProgressBarDialog:IStepProgress
        {
            
            private int maxRange;
            private int minRange;
            private int stepValue;
            private int position;
            private string message;
            private Task task;
            private ProgressBarForm progressBarForm;
            private CancellationTokenSource cancellationTokenSource;
            private ITrackCancel trackCancel;
    
    
            public Form ParentForm { get; set; }
    
    
            public ITrackCancel TrackCancel
            {
                get { return trackCancel; }
                set 
                {
                    if (value != null)
                    {
                        trackCancel = value;
                        trackCancel.Progressor = this;
                    }
                    if(progressBarForm != null)
                        progressBarForm.TrackCancel = value;
                    
                }
            }
    
            public int MaxRange
            {
                get { return maxRange; }
                set
                {
                    if (maxRange != value)
                    {
                        if (progressBarForm != null)
                            progressBarForm.MaxRange = value;
                        maxRange = value;
                    }
                }
            }
    
    
            public int MinRange
            {
                get { return minRange; }
                set
                {
                    if (minRange != value)
                    {
                        if(progressBarForm != null)
                            progressBarForm.MinRange = value;
                        minRange = value;
                    }
                }
            }
    
            public int StepValue
            {
                get { return stepValue; }
                set
                {
                    if (stepValue != value)
                    {
                        if (progressBarForm != null)
                            progressBarForm.StepValue = value;
                        stepValue = value;
                    }
                }
            }
    
            public int Position
            {
                get { return position; }
                set 
                {
                    if (progressBarForm != null)
                        progressBarForm.Position = value;
                    position = value;
                }
            }
    
            public string Message
            {
                get { return message; }
                set
                {
                    if (message != value)
                    {
                        if (progressBarForm != null)
                            progressBarForm.Message = value;
                        message = value;
                    }
                }
            }
    
            private void InitDialog()
            {
                if (progressBarForm == null)
                    progressBarForm = new ProgressBarForm(ParentForm);
                progressBarForm.TopMost = true;
                progressBarForm.MaxRange = this.MaxRange;
                progressBarForm.MinRange = this.MinRange;
                progressBarForm.StepValue = this.StepValue;
                progressBarForm.Position = this.Position;
                if (trackCancel != null)
                    progressBarForm.TrackCancel = this.TrackCancel;
                if (!cancellationTokenSource.IsCancellationRequested)//此处的取消方法不是强制取消,CLR线程管理会在响应后合适的时候取消
                {                                                     //这种线程取消的方式,一个目的是为了解决.NET4.0以前线程强制关闭的异常问题
                    if (progressBarForm.ShowDialog() == DialogResult.OK)
                    {
                        
                    }
                }
            }
    
            public void Show()
            {
                ShowDialog();
            }
    
            public void ShowDialog()
            {
                try
                {
                    cancellationTokenSource = new CancellationTokenSource();
                    task = new Task(InitDialog, cancellationTokenSource.Token);
                    task.Start();
                    //此处创建的延续任务,为确保线程取消的时候,出现异常情况(如:进度UI还没有展示,主方法就已经走完)的保险处理
                    Task cancelTask = task.ContinueWith(
                        (cancellatinTask) =>
                        {
                            if (progressBarForm != null && progressBarForm.Visible)
                                progressBarForm.Hide();
                        }, TaskContinuationOptions.OnlyOnCanceled);
                }
                catch (Exception)
                {
                    throw;
                }
            }
    
            public void HideDialog()
            {
                try
                {
                    if (progressBarForm == null)//当进度窗体还没有显示出来,进度线程监视的方法已经走完,取消task线程
                        cancellationTokenSource.Cancel();
                    else
                    {
                        MethodInvoker invoker = () =>
                            {
                                if (progressBarForm.Visible)
                                    progressBarForm.Hide();
                            };
                        if (progressBarForm.InvokeRequired)
                        {
                            progressBarForm.Invoke(invoker);
                        }
                        else
                        {
                            invoker();
                        }
                    }
                }
                catch (Exception)
                {
                    throw;
                }
            }
    
            public void Hide()
            {
                HideDialog();
            }
    
            public void Step()
            {
                if (progressBarForm != null)
                    progressBarForm.Step();
            }
        }

           实现进度展示的UI类(ProgressBarForm)如下:

    public partial class ProgressBarForm : Form
        {
            public ProgressBarForm(Form parent)
            {
                InitializeComponent();
                InitLocation(parent);
            }
    
            private void InitLocation(Form parent)
            {
                if (parent != null)
                {
                    Left = parent.Left + (parent.Width - Width) / 2;
                    Top = parent.Top + (parent.Height - Height) / 2;
                }
            }
    
            private int maxRange;
            private int minRange;
            private int stepValue;
            private int position;
            private string message;
    
            public ITrackCancel TrackCancel { get; set; }
    
            public string Message
            {
                get { return message; }
                set
                {
                    if (message != value)
                    {
                        MethodInvoker invoker = () => lab_Message.Text = value; ;
                        if (lab_Message.InvokeRequired)
                        {
                            //lab_Message.Invoke(invoker);
                            IAsyncResult asyncResult =lab_Message.BeginInvoke(invoker);
                            lab_Message.EndInvoke(asyncResult);
                        }
                        else
                        {
                            invoker();
                        }
                        message = value;
                    }
                }
            }
    
            public int MaxRange
            {
                get { return maxRange; }
                set
                {
                    if (maxRange != value)
                    {
                        progressBar1.Maximum = value;
                        maxRange = value;
                    }
                }
            }
    
            public int MinRange
            {
                get { return minRange; }
                set
                {
                    if (minRange != value)
                    {
                        progressBar1.Minimum = value;
                        minRange = value;
                    }
                }
            }
    
            public int StepValue
            {
                get { return stepValue; }
                set
                {
                    if (stepValue != value)
                    {
                        progressBar1.Step = value;
                        stepValue = value;
                    }
                }
            }
    
            public int Position
            {
                get { return position; }
                set
                {
                    if (position != value)
                    {
                        progressBar1.Value = value;
                        position = value;
                    }
                }
            }
    
            public void Step()
            {
                MethodInvoker invoker = () =>
                    {
                        int newValue = progressBar1.Value + this.StepValue;
                        //当进度超过最大值,默认赋最小值
                        if (newValue > this.MaxRange)
                        {
                            progressBar1.Value = MinRange;
                            progressBar1.Refresh();
                        }
                        else
                        {
                            progressBar1.Value = newValue;
                            progressBar1.Refresh();
                        }
                    };
                if (progressBar1.InvokeRequired)
                {
                    //progressBar1.Invoke(invoker);
                    //采用异步委托的方法,提高进度条的响应速度,不知道线程创建多会不会影响效率(PS:没有研究过异步委托创建线程的方式,不知道是从线程池那线程,还是每次来就创建一个)
                    IAsyncResult asyncResult =progressBar1.BeginInvoke(invoker);
                    progressBar1.EndInvoke(asyncResult);
                }
                else
                {
                    invoker();
                }
            }
    
            private void ProgressBarForm_KeyDown(object sender, KeyEventArgs e)
            {
                if( e.KeyCode == Keys.Escape && TrackCancel.CancelOnKeyPress)
                    TrackCancel.Cancel();
            }
    
            private void btn_Cancel_Click(object sender, EventArgs e)
            {
                if (TrackCancel.CancelOnClick)
                {
                    TrackCancel.Cancel();
                }
            }
    
            protected override void OnPaint(PaintEventArgs e)
            {
                base.OnPaint(e);
                //当中断处理不支持按钮取消时候,将取消按钮不显示
                if (!TrackCancel.CancelOnClick)
                {
                    this.Height = 65;
                }
            }
        }

             下面完成对进度的调用进度条的简单封装类(DialogManager)如下:

         /// <summary>
         /// 管理进度条的方法类
         /// </summary>
        public class ProgressManager
        {
            public static IStepProgress ShowProgressBarDialog(ITrackCancel trackCancel,Form pForm)
            {
                if (trackCancel == null)
                    return null;
                return new ProgressBarDialog() {TrackCancel = trackCancel,ParentForm = pForm};
            }
    
            public static IStepProgress ShowProgressBarDialog(ITrackCancel trackCancel, Form pForm,int maxRange,int minRange,int stepValue)
            {
                if (trackCancel == null)
                    return null;
                return new ProgressBarDialog()
                    {
                        TrackCancel = trackCancel,
                        ParentForm = pForm,
                        MaxRange = maxRange,
                        MinRange = minRange,
                        StepValue = stepValue
                    };
            }
        }

              最后,在自己代码中调用进度的写法如下:

             private void button1_Click(object sender, EventArgs e)
            {
                ITrackCancel trackCancel = new CancelTracker() {CancelOnClick = true, CancelOnKeyPress = true};
                IStepProgress stepProgress = ProgressManager.ShowProgressBarDialog(trackCancel,this);
                stepProgress.MinRange = 0;
                stepProgress.MaxRange = 100;
                stepProgress.StepValue = 1;
                bool pContinue = true;
                stepProgress.Show();
                for (int i = 0; i < 100; i++)
                {
                    stepProgress.Message = String.Format("正在计算{0}...",i);
                    pContinue = trackCancel.Continue();
                    if(!pContinue)
                        break;
                    stepProgress.Step();
                    Thread.Sleep(50);
                }
                stepProgress.Hide();
    
            }

               以上为对简单进度条的封装过程,接口的定义参考了ArcGIS的接口定义方式。如果想增加对其它的进度条的支持,需要实现对应的进度条接口和对应的展示UI即可。如:想增加一个转圈等待的进度条展示进度,你只需要实现IProgressor接口,想支持中断处理,实例化实现ITrackCancel接口的类即可,可以用工厂模式来管理你的进度条展示。

             题外的话:最近在学习fyiReporting和SharpDeveloper的源代码,fyiReporting的源代码太多,网上没发现什么知道的资源,看起来还是一知半解。SharpDeveloper的源码,网上资源大都讲的都是关于插件框架的东西,还有SharpDeveloper的团队也出过一本书的,讲的都是很久以前的版本。在此,求园友们对此感兴趣的能指导下学习fyiReporting或者SharpDeveloper的资料,或者一起共同学习。

            本文的Demo:下载地址

  • 相关阅读:
    pytest.mark.parametrize里面indirect参数详细解释
    linux环境安装python环境
    gitlab怎么给别人新增项目权限
    VMware虚拟机下的CentOS7如果Ping不通百度,解决办法
    ip configuration could not be reserved (no available address timeout etc.)虚拟机连接不上网卡解决办法
    虚拟机安装教程
    auto_now与auto_now_add之间的区别
    【二分答案】洛谷P2678 [NOIP2015 提高组] 跳石头/P1824 进击的奶牛/P2440木材加工/P1873 砍树
    团体程序设计天梯赛PTA L2-021点赞狂魔
    团体程序设计天梯赛PTA L2-020功夫传人
  • 原文地址:https://www.cnblogs.com/Johnnie/p/3496607.html
Copyright © 2011-2022 走看看