---
title: "BackgroundWorker implementation -in C#"
url: "https://osherove.com/blog/2004/6/16/backgroundworker-implementation-in-c.md"
canonical: "https://osherove.com/blog/2004/6/16/backgroundworker-implementation-in-c.html"
published: "2004-06-16T07:20:00"
updated: "2004-06-16T07:20:00"
tags: ["Other"]
author: "Roy Osherove"
description: "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…"
usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)."
license: "https://creativecommons.org/licenses/by/4.0/"
---

# BackgroundWorker implementation -in C\#

By Roy Osherove June 16, 2004 In [Other](https://osherove.com/blog/category/other)

**Historical article** · Originally published June 16, 2004; technical details may be outdated.

BackgroundWorker class – built using instructions from [this fine article by Juval](http://www.devx.com/codemag/Article/20639?trk=DXRSS_DOTNET).

---

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

}

## More in Other

[All posts in Other](https://osherove.com/blog/category/other)

- Dec 6, 2006

    ### [I screwed up with a client. Here's what I've learned.](https://osherove.com/blog/2006/12/6/i-screwed-up-with-a-client-heres-what-ive-learned.html)

- Sep 3, 2004

    ### [Review - JetBrains Resharper](https://osherove.com/blog/2004/9/3/review-jetbrains-resharper.html)

- Feb 17, 2004

    ### [Make your .Net application support scripting - a practical approach](https://osherove.com/blog/2004/2/17/make-your-net-application-support-scripting-a-practical-appr.html)

- Jan 17, 2004

    ### [Learning from mistakes: the Don Quixote pattern](https://osherove.com/blog/2004/1/17/learning-from-mistakes-the-don-quixote-pattern.html)


---

## About the author

**Roy Osherove**: Senior Solutions Architect at AWS working on AI for production and AI-driven development; author of The Art of Unit Testing and Elastic Leadership, with about 20 years of consulting and training on unit testing, TDD, team leadership and continuous delivery.

### Sites

- [RobotPaper](https://robotpaper.ai/): This blog: AI patterns and anti-patterns, AI and coding agents, and engineering leadership.
- [osherove.com](https://osherove.com): Roy's personal site. Author of The Art of Unit Testing and Elastic Leadership; consulting and training on unit testing, TDD, team leadership and continuous delivery, plus about 20 years of blog posts.
- [The Art of Unit Testing](https://www.artofunittesting.com): The Art of Unit Testing, 3rd Edition (Manning): readable, maintainable, trustworthy unit tests, plus TDD workshops in C#, JavaScript, Java and Kotlin.
- [5whys.com](https://www.5whys.com): Roy's writing on software team leadership: self-organizing teams, surviving chaos, learning mode and the Elastic Leadership model.
- [Pipeline Driven](https://pipelinedriven.org): Continuous delivery and DevOps practices: build patterns, pipeline-friendly testing, DevOps metrics and enterprise DevOps.
- [Elastic Leadership](https://www.elasticleadership.com): Elastic Leadership, Roy's framework for software team leaders (survival, learning and self-organizing modes).

### Social

- X: https://x.com/royosherove
- LinkedIn: https://www.linkedin.com/in/osherove/

### Contact

- Contact form: https://forms.gle/jQSx5KoXvrVA1JCK7

### License

Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page). License: https://creativecommons.org/licenses/by/4.0/
