title: winforms: updating progress with a parallel.foreach
body: <p>I haven't seen any posts pertaining to my issue, so I apologize if I post a question already asked.</p>
  
  <p>I have a windows form program, c#, that checks stocks and does analysis.  The main form launches another form, via a new thread and ShowDialog.  While it's loading, it's running a parallel.foreach.  In that parallel.foreach, I'd like to show progress on the main form.</p>
  
  <p>I've run into cross-threading issues, and added invoke, although it doesn't appear to be thread-safe as it seems to be deadlocking toward the end of the parallel.foreach.  I've tried delegates, events, no luck.  Help me Obi-Wans, you're my only hope!</p>
  
  <p>Stripped down version:</p>
  
  <p>Main form</p>
  
  <pre><code>private void button1_Click(object sender, EventArgs e)
      {
          YearLows yearLows = new YearLows();
          Thread yearLowsThread = new Thread(() =&gt; StartYearLows(yearLows));
          yearLowsThread.Start();
          btnGetYearLows.Enabled = false;
      }
  
      private void StartYearLows(YearLows yearLows)
      {
          yearLows.ShowDialog();
      }
  
      public void UpdateProgress(string text)
      {
          lblProgress.Text = text;
      }
  </code></pre>
  
  <p>2nd form dialog</p>
  
  <pre><code>    public partial class YearLows : Form
      {
          private void YearLows_Load(object sender, EventArgs e)
          {
              // work
              Parallel.ForEach(responseStocks, new ParallelOptions { MaxDegreeOfParallelism = MaxThreads }, x =&gt;
              {
                // more work
                Interlocked.Increment(stocksProcessed);
                UpdateProgress($"{stocksProcessed} / {stocksTotal} Researched");
              });
          }
  
          private void UpdateProgress(string text)
          {
              Invoke(new Action(() =&gt; frmMain.UpdateProgress(text)));
          }
      }
  </code></pre>
  
  <p>Update 1:
  If I move the progress update label to the child form, it appears I am getting all the progress updates.  I had to move from the Load event to the Shown event so that the form renders, so users can see the progress updates.  I had to follow SLaks advice though and run Task.Run(() => Parallel.ForEach.  This will work for me.  Would still like to figure out why it still locks up toward the end if I wanted the progress updates on the main form.  (I've always read async void was bad, but I guess no way around this in these defined method signatures in winforms)</p>
  
  <pre><code>    public partial class YearLows : Form
      {
          private async void YearLows_Shown(object sender, EventArgs e)
          {
              await AnalyzeStocks();
          }
  
          private async Task AnalyzeStocks(object sender, EventArgs e)
          {
              // work
              await Task.Run(() =&gt; Parallel.ForEach(responseStocks, new ParallelOptions { MaxDegreeOfParallelism = MaxThreads }, x =&gt;
              {
                  // more work
                  Interlocked.Increment(stocksProcessed);
                  UpdateProgress($"{stocksProcessed} / {stocksTotal} Researched");
              }));
          }
  
          private void UpdateProgress(string text)
          {
              Invoke(new Action(() =&gt; lblProgress.UpdateProgress(text)));
          }
      }
  </code></pre>