title: Running a BackgroundWorker within another BackgroundWorker
body: <p>I'm attempting a very DB intensive task in a project. Here is a walk-through:</p>
  
  <p>We need to search our DB of workers, we called Locums, and find one for a specific job. This procedure starts when we decide to process x number of jobs. So, on the click of a button, we process using the <code>ProcessJobBatch()</code> method. However, this method only process against a very limited number of Locums. So it takes less then 10 seconds to fill up a scheduler control. Now, once the limited number of Locums are served, we need to run a background task to check the rest of the Locums. There are around 1250 of them!</p>
  
  <p>So, once <code>ProcessJobBatch()</code> finishes, a <code>BackgroundWorker</code>, <code>BackgroundWorkerMoreLocums</code>, goes off. Now, this worker basically does a simple loop: For each job, go through the whole 1250 employees. This takes way too long. I need to plan this out using an alternate strategy that I can't of ATM or I need to show a secondary progress bar for the inner for-each loop.</p>
  
  <p><strong>More Explanation:</strong> We import a batch of Jobs (10 to 70) numerous times on daily bases. Once a batch is imported, the application instructs the logged-in user to "Preference Find" those newly created jobs. The user already has a list of his favorite locums (1 to 20). He wants to distribute the jobs among his favorites first. That is done through <code>ProcessJobBatch()</code>. But, there are two scenarios that prevent the flow there and then: </p>
  
  <ul>
  <li>What if certain jobs didn't fall to
  any favorite locum?</li>
  <li>What if there is a locum in the whole
  DB who can do almost all the jobs but
  since he isn't favorite?</li>
  </ul>
  
  <p>So, I end up with a scenario of matching a job with each Locum.</p>
  
  <p><strong>Question:</strong> 
  Can second BackgroundWorker run within a BackgroundWorker's DoWork?
  Am I doing the second scan wrong?</p>
  
  <p><strong>Environment:</strong> Windows 7 Pro 64-bit, Visual Studio 2010, C#, .NET 4.0, and Windows Forms</p>
  
  <pre><code>    private void ButtonPreferenceFind_Click(object sender, EventArgs e) {
          if (LookUpBatches.EditValue != null) {
              JobBatch JobBatchSelected = DbContext.JobBatches.FirstOrDefault(job_batch=&gt; job_batch.OID == LookUpBatches.EditValue.ToString());
  
              if (JobBatchSelected != null &amp;&amp; JobBatchSelected.Jobs.Count(condition =&gt; condition.JobStatusID == 1) &gt; 0) {
                  if (XtraMessageBox.Show(String.Format("Are you sure to process {0} job(s)?", JobBatchSelected.Jobs.Count(condition =&gt; condition.JobStatusID == 1)), Text, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) {
                      ProcessJobBatch(JobBatchSelected);
  
                      IEnumerable&lt;Job&gt; SpecificJobs = from req_jobs in JobBatchSelected.Jobs
                                                                                      where req_jobs.JobStatusID == 1
                                                                                      select req_jobs;
  
                      ProgressBarControlPreferenceFinder.EditValue = 0;
                      ProgressBarControlPreferenceFinder.Properties.Minimum = 0;
                      ProgressBarControlPreferenceFinder.Properties.Maximum = SpecificJobs.Count() - 1;
  
                      BackgroundWorkerMoreLocums.RunWorkerAsync(SpecificJobs);
  
                  } else {
                      LookUpBatches.Focus();
                  }
  
              } else {
                  XtraMessageBox.Show("Unable to retrieve the selected batch or the batch has no processable jobs.", Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                  LookUpBatches.Focus();
  
              }
  
          } else {
              XtraMessageBox.Show("Select a batch first.", Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);                   
              LookUpBatches.Focus();
  
          }
      }
  
      #region Background Searching
      private void BackgroundWorkerMoreLocums_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) {
          try {
              e.Result = GetTableData(e.Argument);
  
          }
          catch (Exception ex) {
              XtraMessageBox.Show("Background Error: " + ex.Message, "Excite Engine 2", MessageBoxButtons.OK, MessageBoxIcon.Error);
              e.Result = ex;
          }
      }
  
      private void BackgroundWorkerMoreLocums_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) {
          // only display progress, do not assign it to grid          
          ProgressBarControlPreferenceFinder.Increment(e.ProgressPercentage);
      }
  
      private void BackgroundWorkerMoreLocums_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) {
          if (e.Result is DataTable) {
              //dataGridView1.DataSource = e.Result as DataTable;
          }
          else if (e.Result is Exception) {
          }
      }
  
      private DataTable GetTableData(Object JobList) {
          DataTable ResultDataTable = new DataTable();
          ResultDataTable.Columns.Add();
  
  
          IEnumerable&lt;Job&gt; JobBatchSelected = (IEnumerable&lt;Job&gt;)JobList;
  
          IEnumerable&lt;Locum&gt; LeftOverLocums = from lefties in DbContext.Locums
                                                                                  //where SchedulerMatrixStorage.Resources.Items.Select(res =&gt; (long)res.Id).ToList().Contains(lefties.OID) == false
                                                                                  select lefties;
  
          int NumOfJobsProcessed = 0;
  
          List&lt;KeyValuePair&lt;long, TemporaryPreferenceFindLocum&gt;&gt; AlreadyPrefferedLocums = new List&lt;KeyValuePair&lt;long, TemporaryPreferenceFindLocum&gt;&gt;();
  
          foreach (Job oneJob in JobBatchSelected) {
  
              foreach (Locum oneLocum in LeftOverLocums) {
  
                  if (DbContext.Availabilities.Any(check =&gt; check.LocumID == oneLocum.OID &amp;&amp; check.AvailableDate == oneJob.JobDate &amp;&amp; check.AvailabilityStatusID == 1)) {
                      //This Locum can do this job
  
                      //Now check if he/she has been just alloted
                      if (AlreadyPrefferedLocums.Any(search =&gt; search.Key == oneLocum.OID &amp;&amp; search.Value.JobDate == oneJob.JobDate) == false) {
                          //No? Cool!                     
                          //Add to the list to prevent double allocation
                          AlreadyPrefferedLocums.Add(new KeyValuePair&lt;long, TemporaryPreferenceFindLocum&gt;(oneJob.OID, new TemporaryPreferenceFindLocum(oneJob.JobDate, oneJob.OID, oneLocum.OID, oneLocum.FirstName + " " + oneLocum.LastName)));
  
                      }
                      else {
                          continue;
  
                      }
  
                  }
                  else {
                      //Not marked as Avaliable on the required job date...
                      continue;
  
                  }
  
              }
  
              NumOfJobsProcessed++;
              BackgroundWorkerMoreLocums.ReportProgress((int)(NumOfJobsProcessed * 100F / (JobBatchSelected.Count() - 1)));
          }
  
          return ResultDataTable;
      }
      #endregion
  </code></pre>