title: Updating UI from Parallel ForEach
body: <p>I am currently working on a side project where I have to process a lot of data regarding virtual machines using <code>ManagementObject</code> to get information about each machine.</p>
  <p>I want to be able to process each virtual machine I find in parallel, updating a progress bar after each iteration is complete (and therefore that virtual machine is done being processed). Currently I have a total of about 81 VMs. I have a simple button in WPF that fires this off:</p>
  <pre><code>        ClusterCrawler testCrawler = new ClusterCrawler(&quot;MyCluster&quot;);
          StartButton.IsEnabled = false;
          List&lt;RTClusterNode&gt; clustNodeParallel = null;
          clustNodeParallel = await Task.Run(()=&gt;testCrawler.CrawlAndReturnNodesParrallelAsync(CrawlProgressBar));
  </code></pre>
  <p>Where <code>CrawlProgressBar</code> is a <code>ProgressBar</code> in the Main Window where the button is.</p>
  <p>The <code>CrawlAndReturnNodesParallelAsync</code> method exist inside my <code>ClusterCrawler</code> class and processes a list of virtual machines, but at the end it uses a <code>ParallelForEach</code> loop to speed up the processing:</p>
  <pre><code>        public async Task&lt;List&lt;RTClusterNode&gt;&gt; CrawlAndReturnNodesParrallelAsync(ProgressBar pBar)
          {
              //Some processing done here
              
              int count = 0;
              Parallel.ForEach(clusterNodes_hr, node =&gt;
              {
                  foreach (var vm in node.VmList)
                  {
                      Console.WriteLine(&quot;Crawling VM: &quot; + vm.VmName);
                      VirtualMachineCrawler vmCrawler = new VirtualMachineCrawler(vm);
                      vmCrawler.CrawlForDataDiskSpace();
                      Interlocked.Increment(ref count);
                      Console.WriteLine(&quot;Current count: &quot; + count);
                      Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)delegate(){
                          pBar.Value = count;
                      });
                  }
              });
              return clusterNodes_hr;
          }
  </code></pre>
  <p>I feel like I am not using the <code>Dispatcher</code> properly here, because even when I try to I still get exceptions that say that the thread cannot access this object (the progress bar) because it does not own it.</p>
  <p>Any ideas as to how I can update the progress bar as the parallel for each loop executes?</p>
  <p><strong>Edit:</strong></p>
  <p>@Servy had the right answer for this. I also noticed an issue higher up in the code that I had not spotted until now. Higher up inside <code>CrawlAndReturnNodesParallelAsync</code>, I had the following line:</p>
  <pre><code>pBar.Maximum = totalVms;
  </code></pre>
  <p>I did not notice this before because when I attach the debugger to the remote machine that I am running the code on, the debugger always times out before I get a chance to see exactly what line the code failed on. I've posted about this issue on here but have yet to get to the bottom of it.</p>
  <p>Besides that, due to time constraints, I did a hybrid of my previous solution as well as @Servy's. My <code>Button</code> code now includes this:</p>
  <pre><code>IProgress&lt;int&gt; progress = new Progress&lt;int&gt;(n =&gt; CrawlProgressBar.Value = n);
  clustNodeParallel = await Task.Run(()=&gt;testCrawler.CrawlAndReturnNodesParrallelAsync(progress, CrawlProgressBar));
  </code></pre>
  <p>And the actual method signature was changed to:</p>
  <pre><code>public List&lt;RTClusterNode&gt; CrawlAndReturnNodesParrallelAsync(IProgress&lt;int&gt; progress, ProgressBar pBar)
  </code></pre>
  <p>I used @Servy's solution here:</p>
  <pre><code>Parallel.ForEach(clusterNodes_hr, node =&gt;
  {
      foreach (var vm in node.VmList)
      {
          Console.WriteLine(&quot;Crawling VM: &quot; + vm.VmName);
          VirtualMachineCrawler vmCrawler = new VirtualMachineCrawler(vm);
          vmCrawler.CrawlForDataDiskSpace();
          Interlocked.Increment(ref count);
          Console.WriteLine(&quot;Current count: &quot; + count);
          progress.Report(count);
      }
  });
  </code></pre>
  <p>But I also used my earlier solution that I had originally a few lines up to fix the issue when I was setting the maximum value for the <code>ProgressBar</code>:</p>
  <pre><code>Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)delegate()
  {
      pBar.Maximum = totalVms;
  });
  </code></pre>