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

      前面写了几篇关于线程、BackGroundWorker等一下文章,现在主要对这些文章进行一个总结,写一篇关键异步窗体的,来实现操作的进度。

     对于大型作业来说,循环处理是一件极其耗时的事情,如果都在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(0false);
            }
        }

        
/// <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"><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(
01000);
                
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();
                }
            }

        } 

示例代码下载 :ProgressWindow源代码

 

 

posted @ 2009-11-26 14:59 萧萧空间 阅读(...) 评论(...) 编辑 收藏