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

对于大型作业来说,循环处理是一件极其耗时的事情,如果都在Application的主线程中去执行,用户的界面感觉就如同死机一般,但是如果添加了进度窗体(ProcessWindow)来说,就不同了,程序会显示出一个新的窗体,而且给用户的效果是非常好的。

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

 

     

processbuilder window 发送多个命令 processing window_System

 

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

首先创建一个项目,名叫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();
                }
            }
        } 

示例代码下载 :ProgressWindow源代码