title: Understanding BackgroundWorker
body: <p>I would like to understand how <code>BackgroundWorker</code> is being used.
  I have tried to break it down to a Console C# project, actually it is a Windows Form Application, where a button triggers the execution of three background tasks. When the button is pressed, it should become disabled preventing further button events. When all three tasks have finished, the button should be enabled again. Also the success of the three tasks should be tested in the main thread. To prevent from mixing this all into a Forms app, I'm trying now to understand the basics and move that to the Forms application.
  (From the comments settings you may guess where my problems of understanding are)
  Consider this (still erroneous) code:</p>
  
  <pre><code>using System;
  using System.ComponentModel;
  using System.Linq;
  using System.Text;
  using System.Threading;
  
  namespace BGWorkerConsoleApp
  {
      class Program
      {
  
  //        #region BackgroundWorker
  //
  private System.ComponentModel.BackgroundWorker worker = new System.ComponentModel.BackgroundWorker();
  
  //
  //        #endregion
          static void Main(string[] args)
          {
  //            BackgroundWorker worker = new System.ComponentModel.BackgroundWorker();
  
              worker.RunWorkerCompleted += TestComplete;
              worker.DoWork += TestConnection1;
  //            worker.DoWork += TestConnection2;
  //            worker.DoWork += TestConnection3;
              DoWorkEventArgs e = new DoWorkEventArgs(); // ???
  
              worker.RunWorkerAsync(e); // ???
          }
  
          private void TestConnection1(object sender, DoWorkEventArgs e)
          {
              bool success = false;
              Thread.Sleep(14000); // stands for some time consuming Task
              success = true;
              e.Result = success;
          }
          private void TestConnection2(object sender, DoWorkEventArgs e)
          {
              bool success = false;
              Thread.Sleep(10000); // stands for some time consuming Task
              success = true;
              e.Result = success;
          }
          private void TestConnection3(object sender, DoWorkEventArgs e)
          {
              bool success = false;
              Thread.Sleep(5000); // stands for some time consuming Task
              success = true;
              e.Result = success;
          }
  
          private void TestComplete(object sender, RunWorkerCompletedEventArgs e)
          {
              Console.WriteLine("complete");
          }
  
      }
  }
  </code></pre>
  
  <p>My questions:</p>
  
  <p>Can I add more than one Task to a <code>BackgroundWorker</code>? Probably not, since there is only one RunWorkerAsync. Assuming I need a worker for every task, how would I wait for all three tasks to complete?</p>
  
  <p>OK, let me change it to a Forms application since the stress doesn't lay on running BackGroundworker in a console App, rather I would like to understand how to design the application for more than one BackGroundWorkers and wait for their completion (including the passing and returning of parameters and results.</p>
  
  <p>Here is the code for the same in a Form app:</p>
  
  <pre><code>using System;
  using System.Windows.Forms;
  using System.ComponentModel;
  using System.Threading;
  
  namespace BackGroundWorkerForm
  {
      partial class Form1
      {
          /// &lt;summary&gt;
          /// Required designer variable.
          /// &lt;/summary&gt;
          private System.ComponentModel.IContainer components = null;
  
  
          private Button button;
          /// &lt;summary&gt;
          /// Clean up any resources being used.
          /// &lt;/summary&gt;
          /// &lt;param name="disposing"&gt;true if managed resources should be disposed; otherwise, false.&lt;/param&gt;
          protected override void Dispose(bool disposing)
          {
              if (disposing &amp;&amp; (components != null))
              {
                  components.Dispose();
              }
              base.Dispose(disposing);
          }
  
          #region Windows Form Designer generated code
  
          /// &lt;summary&gt;
          /// Required method for Designer support - do not modify
          /// the contents of this method with the code editor.
          /// &lt;/summary&gt;
          private void InitializeComponent()
          {
              this.components = new System.ComponentModel.Container();
              this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
              this.Text = "Form1";
              button = new System.Windows.Forms.Button();
              button.Location = new System.Drawing.Point(100, 10);
              button.Name = "button";
              button.Size = new System.Drawing.Size(100, 20);
              button.TabIndex = 5;
              button.Text = "TestConnection";
              button.Click += new System.EventHandler(this.RunTest);
              button.Visible = true;
              Controls.Add(button);
          }
  
          #endregion
  
  
         private void RunTest(object o, EventArgs e)
          {
          BackgroundWorker worker = new System.ComponentModel.BackgroundWorker();
          worker.RunWorkerCompleted += TestComplete;
          worker.DoWork += TestConnection1;
  //            worker.DoWork += TestConnection2;
  //            worker.DoWork += TestConnection3;
  
          worker.RunWorkerAsync();
          }   
          private void TestConnection1(object sender, DoWorkEventArgs e)
          {
              bool success = false;
              Thread.Sleep(10000); // stands for some time consuming Task
              success = true;
              e.Result = success;
          }
          private void TestConnection2(object sender, DoWorkEventArgs e)
          {
              bool success = false;
              Thread.Sleep(10000); // stands for some time consuming Task
              success = true;
              e.Result = success;
          }
          private void TestConnection3(object sender, DoWorkEventArgs e)
          {
              bool success = false;
              Thread.Sleep(10000); // stands for some time consuming Task
              success = true;
              e.Result = success;
          }
  
          private void TestComplete(object sender, RunWorkerCompletedEventArgs e)
          {
              button.Text= "complete";
          }
  
      }
  }
  </code></pre>