Passing variable to BackgroundWorker and use the same value later
BackgroundWorker already has a mechanism for passing and retrieving arguments.  The DoWorkEventArgs has a property for a passed in method argument and a property for the DoWork result.  The RunWorkerCompletedEventArgs has a property for retrieving the result.  No sub-classing is necessary, although you may need to make a custom container if you need to pass/return more than one object.

for (int i = 0; i &lt; 10; i++)
{
  BackgroundWorker bw = new BackgroundWorker ();
  bw.WorkerReportsProgress = false;
  bw.DoWork += delegate(object sender, System.ComponentModel.DoWorkEventArgs eargs)
  {
    int i = (int)eargs.Arugment;  //get argument
    Console.WriteLine(String.Format("Thread {0} started", bw.value));
    System.Threading.Thread.Sleep(bw.value * 1000);
    eargs.Result = i;            //set result
  };
  bw.RunWorkerCompleted += delegate(object sender, System.ComponentModel.RunWorkerCompletedEventArgs eargs)
  {
    int i = (int)eargs.Arugment;  //get argument
    Console.WriteLine(String.Format("Thread {0} finished", i));
  };

  bw.RunWorkerAsync(i);
}