• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1241
  • Last Modified:

Need help with background worker process called from parallel.foreach

I want to process a list of users and update a progress bar as each item s processed.

My implementation is wrong though because I receive an error :
"Cross-Thread operation not valid"

I have been directed to the link below and folowed its implementation but I am unable to circumvent the error.

I have googled a bit and tried a few different strategies but my latest iteration is receiving the same error I received before implementing background worker processes.

The method backgroundWorker1_RunWorkerCompleted is generating the exception.

I appreciate your time.
//Parallel Snippet 
cancelToken = new CancellationTokenSource();
ParallelOptions parOpts = new ParallelOptions();
parOpts.CancellationToken = cancelToken.Token;
parOpts.MaxDegreeOfParallelism =  System.Environment.ProcessorCount;

try
                    {
                        Parallel.ForEach(userIDList, parOpts, user =>
                            {
                                parOpts.CancellationToken.ThrowIfCancellationRequested();
                                _operator.formatEmail(emailFormat, txtEmailDomain.Text, user);
                                UpdateProgress(); //call background processes
                            });
                    }
                    catch (OperationCanceledException ex)
                    {
                        MessageBox.Show("Cancellation in progress: " + ex.Message);
                    }
                    catch (OperationAbortedException ex)
                    {
                        MessageBox.Show("Process aborted. " + ex.Message);
                    }

//create background process
private void UpdateProgress(){
            backgroundWorker1 = new BackgroundWorker();
            backgroundWorker1.WorkerSupportsCancellation = true;
            backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted; 

            this.backgroundWorker1.RunWorkerAsync();
        }


 private void backgroundWorker1_RunWorkerCompleted(
            object sender,
            RunWorkerCompletedEventArgs e)
        {
            
            Interlocked.Increment(ref progressCounter);  //Thread safe increment
            this.pgbarApplyChanges.Value = (progressCounter); //this throws the exception.
            this.lblProgress.Text = (((progressCounter / userIDList.Count()) * 100).ToString() + " % Complete");
            if (progressCounter == userIDList.Count)
            {
                btnFinish.Visible = true;
                Form1.ActiveForm.Refresh();
            }
        }

Open in new window

0
ODOTServer
Asked:
ODOTServer
  • 2
2 Solutions
 
saraganiCommented:
Hi, I don't see any point of starting a background worker from a thread which is not the UI thread.

Please try the following solution:


                  //Parallel Snippet
                  cancelToken = new CancellationTokenSource();
                  ParallelOptions parOpts = new ParallelOptions();
                  parOpts.CancellationToken = cancelToken.Token;
                  parOpts.MaxDegreeOfParallelism =  System.Environment.ProcessorCount;

                  try
                   {
                        Parallel.ForEach(userIDList, parOpts, user =>
                            {
                                parOpts.CancellationToken.ThrowIfCancellationRequested();
                                _operator.formatEmail(emailFormat, txtEmailDomain.Text, user);
                               
                               MethodInvoker mi = delegate()
                               {
                                          Interlocked.Increment(ref progressCounter);  //Thread safe increment
                                          this.pgbarApplyChanges.Value = (progressCounter); //this throws the exception.
                                          this.lblProgress.Text = (((progressCounter / userIDList.Count()) * 100).ToString() + " % Complete");
                                          if (progressCounter == userIDList.Count)
                                          {
                                              btnFinish.Visible = true;
                                              Form1.ActiveForm.Refresh();
                                          }
                               }
                               
                               updateUI(mi);
                            });
                    }
                    catch (OperationCanceledException ex)
                    {
                        MessageBox.Show("Cancellation in progress: " + ex.Message);
                    }
                    catch (OperationAbortedException ex)
                    {
                        MessageBox.Show("Process aborted. " + ex.Message);
                    }






And the code of the updateUI:

                  private void updateUI(MethodInvoker mi)
                  {
                      if (this.InvokeRequired)
                     {
                        this.BeginInvoke(mi);
                     }
                     else
                     {
                        mi();
                     }
                  }
0
 
saraganiCommented:
Oops, my code is missing a ;

you need to add one after the definition of the anonymous method:

                               MethodInvoker mi = delegate()
                               {
                                          Interlocked.Increment(ref progressCounter);  //Thread safe increment
                                          this.pgbarApplyChanges.Value = (progressCounter); //this throws the exception.
                                          this.lblProgress.Text = (((progressCounter / userIDList.Count()) * 100).ToString() + " % Complete");
                                          if (progressCounter == userIDList.Count)
                                          {
                                              btnFinish.Visible = true;
                                              Form1.ActiveForm.Refresh();
                                          }
                               }; // was missing ; here
0
 
ODOTServerAuthor Commented:
Wow.


Thanks! Worked like a champ.
0

Featured Post

Prepare for your VMware VCP6-DCV exam.

Josh Coen and Jason Langer have prepared the latest edition of VCP study guide. Both authors have been working in the IT field for more than a decade, and both hold VMware certifications. This 163-page guide covers all 10 of the exam blueprint sections.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now