Roy Osherove

View Original

BackgroundWorker implementation -in C#

BackgroundWorker class – built using instructions from this fine article by Juval.


 

using System;

using System.ComponentModel;

 

namespace Unique.Shavit.UI

{

      #region BackgroundWorker

      public class BackgroundWorker

      {

            bool m_CancelPending = false;

            bool m_ReportsProgress = false;

            bool m_SupportsCancellation = false;

 

            public event DoWorkEventHandler DoWork;

            public event ProgressChangedEventHandler ProgressChanged;

            public event RunWorkerCompletedEventHandler RunWorkerCompleted;

 

            public bool WorkerSupportsCancellation

            {

                  get

                  {

                        lock(this)

                        {

                              return m_SupportsCancellation;

                        }

                  }

                  set

                  {

                        lock(this)

                        {

                              m_SupportsCancellation = value;

                        }

                  }

            }

 

            public bool WorkerReportsProgress

            {

                  get

                  {

                        lock(this)

                        {

                              return m_ReportsProgress;

                        }

                  }

                  set

                  {

                        lock(this)

                        {

                              m_ReportsProgress = value;

                        }

                  }

            }

 

            public bool CancellationPending

            {

                  get

                  {

                        lock(this)

                        {

                              return m_CancelPending;

                        }

                  }

            }    

 

            public void RunWorkerAsync()

            {

                  RunWorkerAsync(null);

            }

 

            public void RunWorkerAsync(object argument)

            {

                  m_CancelPending = false;

                  if(DoWork != null)

                  {

                        DoWorkEventArgs args = new DoWorkEventArgs(argument);

                        AsyncCallback callback;

                        callback = new AsyncCallback(ReportCompletion);

                        DoWork.BeginInvoke(this,args,callback,args);

                  }

            }

 

            public void ReportProgress(int percent)

            {

                  if(WorkerReportsProgress)

                  {

                        ProgressChangedEventArgs progressArgs;

                        progressArgs = new ProgressChangedEventArgs(percent);                  

                        OnProgressChanged(progressArgs);

                  }

            }

 

            public void CancelAsync()

            {

                  lock(this)

                  {

                        m_CancelPending = true;

                  }

            }

 

            protected virtual void OnProgressChanged(ProgressChangedEventArgs progressArgs)

            {

                  ProcessDelegate(ProgressChanged,this,progressArgs);

            }

 

            protected virtual void OnRunWorkerCompleted(RunWorkerCompletedEventArgs completedArgs)

            {

                  ProcessDelegate(RunWorkerCompleted,this,completedArgs);

            }

 

            public delegate void DoWorkEventHandler(object sender, DoWorkEventArgs e);

            public delegate void ProgressChangedEventHandler(object sender, ProgressChangedEventArgs e);

            public delegate void RunWorkerCompletedEventHandler(object sender, RunWorkerCompletedEventArgs e);

 

 

            void ProcessDelegate(Delegate del,params object[] args)

            {

                  Delegate temp = del;

                  if(temp == null)

                  {

                        return;

                  }

                  Delegate[] delegates = temp.GetInvocationList();

                  foreach(Delegate handler in delegates)

                  {

                        InvokeDelegate(handler,args);

                  }

            }

 

            void InvokeDelegate(Delegate del,object[] args)

            {

                  System.ComponentModel.ISynchronizeInvoke synchronizer;

                  synchronizer = del.Target as System.ComponentModel.ISynchronizeInvoke;

                  if(synchronizer != null) //A Windows Forms object

                  {

                        if(synchronizer.InvokeRequired == false)

                        {

                              del.DynamicInvoke(args);

                              return;

                        }

                        try

                        {

                              synchronizer.Invoke(del,args);

                        }

                        catch

                        {}

                  }  

                  else //Not a Windows Forms object

                  {

                        del.DynamicInvoke(args);

                  } 

            }

 

            void ReportCompletion(IAsyncResult asyncResult)

            {

                  System.Runtime.Remoting.Messaging.AsyncResult ar = (System.Runtime.Remoting.Messaging.AsyncResult)asyncResult;

                  DoWorkEventHandler del;

                  del  = (DoWorkEventHandler)ar.AsyncDelegate;

                  DoWorkEventArgs doWorkArgs = (DoWorkEventArgs)ar.AsyncState;

                  object result = null;

                  Exception error = null;

                  try

                  {

                        del.EndInvoke(asyncResult);

                        result = doWorkArgs.Result;

                  }

                  catch(Exception exception)

                  {

                        error = exception;

                  }

                  RunWorkerCompletedEventArgs completedArgs = new RunWorkerCompletedEventArgs(result, error, doWorkArgs.Cancel);

                  OnRunWorkerCompleted(completedArgs);

            }

 

      }

      #endregion

 

      #region AsyncCompletedEventArgs

 

      public class AsyncCompletedEventArgs : EventArgs

      {    

            public AsyncCompletedEventArgs (bool cancelled,Exception ex)

            {

                  Cancelled= cancelled;

                  Error = ex;

            }

 

            public AsyncCompletedEventArgs(){}

 

            public readonly Exception Error;

            public readonly bool Cancelled;          

      }

      #endregion

 

      #region CancelEventArgs

      public class CancleEventArgs : EventArgs

      {

            private bool m_cancel = false;

            public bool Cancel

            {

                  get

                  {

                        return m_cancel;

                  }

                  set

                  {

                        m_cancel=value;

                  }

            }          

      }

      #endregion

 

      #region DoWorkEventArgs

 

      public class DoWorkEventArgs : CancleEventArgs

      {

            public bool Result

            {

                  get

                  {

                        return false;

                  }

                  set

                  {

                       

                  }

            }

 

            public readonly object Argument;   

 

            public DoWorkEventArgs(object objArgument)

            {

                  Argument = objArgument;

            }

      }

#endregion

 

      #region ProgressChangedEventArgs

 

      public class ProgressChangedEventArgs : EventArgs

      {

            public readonly int ProgressPercentage;        

 

            public ProgressChangedEventArgs (int intProgressPercentage)

            {

                  ProgressPercentage = intProgressPercentage;

            }

      }

      #endregion

 

      #region RunWorkerCompletedEventArgs

 

      public class RunWorkerCompletedEventArgs : AsyncCompletedEventArgs

      {          

            public readonly object Result;

 

            public RunWorkerCompletedEventArgs (object objResult, Exception exException, bool bCancel)

                  :base(bCancel,exException)

            {                

                  Result = objResult;

            }

      }

#endregion

}