title: vb.net update progress bar multithread
body: <p>Long time reader, first time poster.  Usually I'm able to find the answer and make it work.  Not this time..... I'm using VB.NET in VS2013.  I am trying to update a progress bar with work done in a secondary thread.  Easy right?  No. I had to make it more complicated.  The progress bar (<strong>ToolStripProgressBar1</strong>) is on the main form (<strong>frmMain</strong>), the MDI of the project.  A secondary form (<strong>frmShipping</strong>) has a button which initiates a second thread to do some COMM Port communications in a class (<strong>cApex</strong>). I can get the progress bar to update on the <strong>frmMain</strong> from the main UI thread (<strong>frmShipping</strong> button).</p>
  
  <p>This is the code from button on <strong>frmShiping</strong> and the multithread procedure: </p>
  
  <pre><code> Private Sub btnreadScanner_Click(sender As Object, e As EventArgs) Handles btnreadScanner.Click
  
      Dim thrReadScanner As New System.Threading.Thread(AddressOf ReadScanner)
      thrReadScanner.IsBackground = True
      thrReadScanner.Start()
  
  End Sub
  
      Private Sub ReadScanner()
  
      Dim strRowCount As String
      ShipmentMsg(2)
      strRowCount = objShipping.RecordsExisit.ToString()
  
      Try
          objApex.ImmediateMode()
          If objApex.FileDownload = False Then
              Throw New Exception(Err.Description)
          End If
      Catch ex As Exception
          ShipmentMsg(1)
          MessageBox.Show("No Data downloaded from Scanner.  Try Again.  Error#: " &amp; Err.Number &amp; " : " &amp; Err.Description)
          Exit Sub
      End Try
  
      RecordCount()
      DataGridUpdate()
      btnProcessShipment.Enabled = True
      ShipmentMsg(5)
      ScanErrors()
  
  End Sub
  </code></pre>
  
  <p>This all works great.  As expected.  The call to <strong>objApex.FileDownload</strong> in class <strong>cApex</strong> is where progress bar is to be updated from (actually in another function called from FileDownload).  So here is the code there.</p>
  
  <pre><code>Try
          GetHeaderRecord()
          If Count &lt;&gt; 0 Then intTicks = Math.Round((100 / Count), 1)
          For intcount As Integer = 1 To Count
              Dim intLength As Integer = Length
              Do While intLength &gt; 0
                  literal = Chr(_serialPort.ReadChar.ToString)
                  If literal = "&gt;" Then Exit Do
                  strRecord = strRecord &amp; literal
                  intLength = intLength - 1
              Loop
              REF = strRecord.Substring(0, 16).TrimEnd
              SKID = strRecord.Substring(16, 16).TrimEnd
              REEL_BC = strRecord.Substring(32, 15).TrimEnd
              ScanDate = strRecord.Substring(47, 8).TrimEnd
              ScanDate = DateTime.ParseExact(ScanDate, "yyyyMMdd", Nothing).ToString("MM/dd/yyyy")
              ScanTime = strRecord.Substring(55, 6).TrimEnd
              ScanTime = DateTime.ParseExact(ScanTime, "HHmmss", Nothing).ToString("HH:mm:ss")
              strRecordTotal = strRecordTotal &amp; strRecord &amp; CRLF
              Dim strSQL As String
              strSQL = "INSERT INTO tblScanData (PONo,Barcode,SkidNo,ScanDate,ScanTime) " &amp; _
              "VALUES (" &amp; _
             Chr(39) &amp; REF &amp; Chr(39) &amp; _
             "," &amp; Chr(39) &amp; REEL_BC &amp; Chr(39) &amp; _
             "," &amp; Chr(39) &amp; SKID &amp; Chr(39) &amp; _
             "," &amp; Chr(39) &amp; ScanDate &amp; Chr(39) &amp; _
             "," &amp; Chr(39) &amp; ScanTime &amp; Chr(39) &amp; ")"
              objData.Executecommand(strSQL)
              strRecord = ""
          Next
  </code></pre>
  
  <p>And finally this is how I was calling the progress bar update.</p>
  
  <pre><code>Dim f As frmMain = frmMain
  System.Threading.Thread.Sleep(100)
  DirectCast(f, frmMain).ToolStripProgressBar1.PerformStep()
  </code></pre>
  
  <p>I really need to put the PerformStep in the For loop.  Each time around the loop will step the progress bar the percentage of steps needed to make bar fairly accurate (done by the math code before loop).  Also I setup the properties of the progress bar control on <strong>frmMain</strong>. So, am I crazy, or is there a way to accomplish this?  I tried using a delegate; <strong>Me.Invoke(New MethodInvoker(AddressOf pbStep))</strong> to make code cross thread safe.  I don't get an error about cross thread calls, but the progress bar doesn't update either.  Sorry it's a long one but I'm lost and my ADHD won't let me scrap this idea.</p>
  
  <p>EDIT AS REQUESTED:</p>
  
  <pre><code> Public Sub pbStep()
  
      Dim f As frmMain = frmMain
      If Me.InvokeRequired Then
          Me.Invoke(New MethodInvoker(AddressOf pbStep))
      Else
          DirectCast(f, frmMain).ToolStripProgressBar1.PerformStep()
          System.Threading.Thread.Sleep(100)
      End If
  
  End Sub
  </code></pre>