异步窗体实现操作进度(ProgressWindow)

来源:互联网 发布:淘宝嘉年华和双11 编辑:程序博客网 时间:2024/06/07 04:41
对于大型作业来说,循环处理是一件极其耗时的事情,如果都在Application的主线程中去执行,用户的界面感觉就如同死机一般,但是如果添加了进度窗体(ProcessWindow)来说,就不同了,程序会显示出一个新的窗体,而且给用户的效果是非常好的。

    闲话少说,首先讲一下简单的原理:一般处理这样的事情都是一种模式,就是使用多线程或者使用微软封装好的线程控件(BackgroundWorker)去处理。原理都是一样的,就是在主线程中创建一个新的线程,我们成为子线程,子线程和主线程是并行工作的,主线程显示一个模式窗体,显示给用户看,子线程则去处理我们复杂的作业,并且提示主线程显示的模式窗体进度。知道子线程处理完一切作业,则通知模式窗体关闭或者进行其他的处理,流程图如下:


这是简单的流程,下面是代码的实现:

      首先创建一个项目,名叫ProgressWindowForm,然后创建一个窗体名称叫做ProgressWindowForm,首先设置这个窗体不能最大化和关闭,在窗体上添加一个Progressbar、一个Label和Cancel按钮,代码如下:

        #region 委托
        /// <summary>
        /// 设置显示值的委托
        /// </summary>
        /// <param name="text"></param>
        public delegate void SetTextInvoker(String text);


        /// <summary>
        /// 进度显示的委托
        /// </summary>
        /// <param name="val"></param>
        public delegate void IncrementInvoker(int val);


        /// <summary>
        /// 跳转到
        /// </summary>
        /// <param name="val"></param>
        public delegate void StepToInvoker(int val);


        /// <summary>
        /// 设置ProgressBar的范围
        /// </summary>
        /// <param name="minimum"></param>
        /// <param name="maximum"></param>
        public delegate void RangeInvoker(int minimum, int maximum);
        #endregion


        #region 私有变量
        /// <summary>
        /// tilte
        /// </summary>
        private String title = "";


        /// <summary>
        /// 初始线程
        /// </summary>
        private System.Threading.ManualResetEvent initResetEvent = new System.Threading.ManualResetEvent(false);


        /// <summary>
        /// 停止线程
        /// </summary>
        private System.Threading.ManualResetEvent abortResetEvent = new System.Threading.ManualResetEvent(false);


        /// <summary>
        /// 是否关闭
        /// </summary>
        private bool requiresClose = true;
        #endregion


        #region 方法
        /// <summary>
        /// 开始进程
        /// </summary>
        /// <param name="minimum">progressbar的最大值</param>
        /// <param name="maximum">progressbar的最大值</param>
        public void BeginThread(int minimum, int maximum)
        {
            initResetEvent.WaitOne();
            Invoke(new RangeInvoker(DoBegin), new object[] { minimum, maximum });
        }


        /// <summary>
        /// 开始进程
        /// </summary>
        public void BeginThread()
        {
            initResetEvent.WaitOne();
            Invoke(new MethodInvoker(DoBegin));
        }


        /// <summary>
        /// 设置范围
        /// </summary>
        /// <param name="minimum">最小值</param>
        /// <param name="maximum">最大值</param>
        public void SetProgressRange(int minimum, int maximum)
        {
            initResetEvent.WaitOne();
            Invoke(new RangeInvoker(DoSetRange), new object[] { minimum, maximum });
        }


        /// <summary>
        /// 设置显示值
        /// </summary>
        /// <param name="text">显示值</param>
        public void SetDisplayText(String text)
        {
            Invoke(new SetTextInvoker(DoSetText), new object[] { text });
        }


        /// <summary>
        /// 增加显示值
        /// </summary>
        /// <param name="val">增加值</param>
        public void Increment(int val)
        {
            Invoke(new IncrementInvoker(DoIncrement), new object[] { val });
        }


        /// <summary>
        /// 跳到摸个进度
        /// </summary>
        /// <param name="val"></param>
        public void StepTo(int val)
        {
            Invoke(new StepToInvoker(DoStepTo), new object[] { val });
        }




        /// <summary>
        /// 是否停止
        /// </summary>
        public bool IsAborting
        {
            get
            {
                return abortResetEvent.WaitOne(0, false);
            }
        }


        /// <summary>
        /// 结束进程
        /// </summary>
        public void End()
        {
            if (requiresClose)
            {
                Invoke(new MethodInvoker(DoEnd));
            }
        }
        #endregion


        #region 私有方法
        private void DoSetText(String text)
        {
            label.Text = text;
        }


        private void DoIncrement(int val)
        {
            progressBar.Increment(val);
            UpdateStatusText();
        }


        private void DoStepTo(int val)
        {
            progressBar.Value = val;
            UpdateStatusText();
        }


        private void DoBegin(int minimum, int maximum)
        {
            DoBegin();
            DoSetRange(minimum, maximum);
        }


        private void DoBegin()
        {
            cancelButton.Enabled = true;
        }


        private void DoSetRange(int minimum, int maximum)
        {
            progressBar.Minimum = minimum;
            progressBar.Maximum = maximum;
            progressBar.Value = minimum;
            title = Text;
        }


        private void DoEnd()
        {
            Close();
        }


        private void UpdateStatusText()
        {
            Text = title + String.Format(" - {0}% 已完成", (progressBar.Value * 100) / (progressBar.Maximum - progressBar.Minimum));
        }


        /// <summary>
        /// 强制停止进程
        /// </summary>
        private void AbortWork()
        {
            abortResetEvent.Set();
        }
        #endregion


        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Form.Load"/> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);


            initResetEvent.Set();
        }


        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Form.Closing"/> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.ComponentModel.CancelEventArgs"/> that contains the event data.</param>
        protected override void OnClosing(CancelEventArgs e)
        {
            requiresClose = false;
            AbortWork();
            base.OnClosed(e);
        }

就这些,很简单的实现。

测试代码如下:

       /// <summary>
        /// Handles the Click event of the buttonTest control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void buttonTest_Click(object sender, EventArgs e)
        {
            ProgressWindowForm progressWindowForm = new ProgressWindowForm();
            progressWindowForm.Text = "测试工作";
            System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(DoSomeWork), progressWindowForm);
            progressWindowForm.ShowDialog();
        }


        /// <summary>
        /// Does some work.
        /// </summary>
        /// <param name="status">The status.</param>
        private void DoSomeWork(object status)
        {
            ProgressWindowForm progressWindowForm = status as ProgressWindowForm;
            try
            {
                progressWindowForm.BeginThread(0, 1000);
                for (int i = 0; i < 1000; ++i)
                {
                    progressWindowForm.SetDisplayText(String.Format("处理第{0}条.", i));
                    progressWindowForm.StepTo(i);
                    if (progressWindowForm.IsAborting)
                    {
                        return;
                    }
                    System.Threading.Thread.Sleep(100);
                    if (progressWindowForm.IsAborting)
                    {
                        return;
                    }
                }
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.Message + Environment.NewLine + exception.StackTrace);
            }
            finally
            {
                if (progressWindowForm != null)
                {
                    progressWindowForm.End();
                }
            }


        }


//////////////////////////////////////////////////////////////////////////////

demo   http://u.115.com/file/clvi9nic#
ProgressWindow.rar

原创粉丝点击