title: vb net update UI controls from separate thread event
body: <p>I have one class called SFTPConnectorManager.vb which is responsible for managing FTP connections to a server. I Have Form1.vb class which is the main GUI. I want to update a ProgressBar that resides on the Form1 to show the Progress of a file transfer. The function responsible for initiating a connection with the FTP server is started on a new thread, this allows form1 to not be frozen, which is good, however the challenge for me is being able to update the progress bar, which is not working out for me at all.</p>
  
  <p><strong>What I have tried/done:</strong></p>
  
  <ol>
  <li>Using a delegate to update the UI from the separate thread</li>
  <li>Using background worker and using it's progress changed event, I thought I might be on to something here but then I remembered that the update to the UI needs to happen during a file transfer event, specifically SessionFileTransferProgress, not for when I raise a progress changed event.</li>
  <li>Read well over 20 pages worth of documentation in regards to multi-threading and event handling, still don't understand it I guess... </li>
  </ol>
  
  <p><strong>What I need to happen:</strong></p>
  
  <ol start="4">
  <li>Updates to the progress bar UI control, update WHILE a file transfer is in progress, and it needs to not freeze the UI, so it needs to be running on a separate thread (which I have achieved thus far I believe)</li>
  </ol>
  
  <p><strong>Code I am using:</strong></p>
  
  <ol>
  <li><a href="https://winscp.net/eng/docs/library_session" rel="nofollow">https://winscp.net/eng/docs/library_session</a></li>
  <li><a href="https://winscp.net/eng/docs/library_session_filetransferprogress" rel="nofollow">https://winscp.net/eng/docs/library_session_filetransferprogress</a></li>
  </ol>
  
  <p>Form1.vb</p>
  
  <pre><code> Public Sub sub1(ByVal x As Integer, y As Integer)
      StatusLabel2.Text = "Connected"
      ProgressBar1.Maximum = ProgressBar1.Maximum + x
      ProgressBar1.Value = ProgressBar1.Value + y
  
  End Sub
  
  Private Sub Button1_Click(sender As Object, e As EventArgs) Handles StartBtn.Click
      '    If (BackgroundWorker1.IsBusy) &lt;&gt; True Then
      '        BackgroundWorker1.RunWorkerAsync()
      '    End If
  
      'Call Xml reader To Get respective values And store them into Class Property
  
      Dim oConnect = New SFTPConnectorManager
      Dim oXmlRead As XmlReader = XmlReader.Create("D:\dale_documents\projects\programming\vbnet\remote_data_backup\sftp_backup\settings.xml")
  
      While (oXmlRead.Read())
  
          Dim eType = oXmlRead.NodeType
  
          If (eType = XmlNodeType.Element) Then
  
              If (oXmlRead.Name = "HostName") Then
                  oConnect.HostName = oXmlRead.ReadInnerXml.ToString
              End If
  
              If (oXmlRead.Name = "UserName") Then
                  oConnect.UserName = oXmlRead.ReadInnerXml.ToString
              End If
  
              If (oXmlRead.Name = "Password") Then
                  oConnect.Password = oXmlRead.ReadInnerXml.ToString
              End If
  
              If (oXmlRead.Name = "Port") Then
                  oConnect.Port = oXmlRead.ReadInnerXml.ToString
              End If
  
              If (oXmlRead.Name = "Protocol") Then
                  oConnect.ProtocolSelection = oXmlRead.ReadInnerXml.ToString
              End If
  
              If (oXmlRead.Name = "FTPMode") Then
                  oConnect.FtpModeSelection = oXmlRead.ReadInnerXml.ToString
              End If
  
              If (oXmlRead.Name = "SSHFingerPrint") Then
                  oConnect.SSHKey = oXmlRead.ReadInnerXml.ToString
              End If
  
              If (oXmlRead.Name = "Remotepath") Then
                  oConnect.RemotePath = oXmlRead.ReadInnerXml.ToString
              End If
  
              If (oXmlRead.Name = "Localpath") Then
                  oConnect.LocalPath = oXmlRead.ReadInnerXml.ToString
              End If
          End If
  
      End While
  
      Dim eProtocolOptions = oConnect.ProtocolSelection
      Dim sUserName = oConnect.UserName
      Dim sHostName = oConnect.HostName
      Dim sPassword = oConnect.Password
      Dim sSSHKey = oConnect.SSHKey
      Dim iPort = oConnect.Port
      Dim sRemotePath = oConnect.RemotePath
      Dim sLocalPath = oConnect.LocalPath
      Dim bFlag = oConnect.bFlag
  
  
      Dim asOptions = New String() {eProtocolOptions, sHostName, sUserName, iPort, sPassword, sSSHKey, sRemotePath, sLocalPath}
  
      oConnect.TestThread(asOptions)
  </code></pre>
  
  <p>SFTPConnectorManager.vb</p>
  
  <pre><code>Function StartConnectionThread(asOptions)
  
      Try
          Dim oSessionOptions As New SessionOptions
          With oSessionOptions
              .Protocol = ProtocolSelection
              .HostName = HostName
              .UserName = UserName
              .PortNumber = Port
              .Password = Password
              .SshHostKeyFingerprint = SSHKey
          End With
  
          Using oSession As New Session
              AddHandler oSession.FileTransferProgress, AddressOf SessionFileTransferProgress
              oSession.Open(oSessionOptions)
  
              Dim oTransferOptions As New TransferOptions
              oTransferOptions.TransferMode = TransferMode.Binary
  
              oSession.GetFiles(RemotePath, LocalPath, False, oTransferOptions)
  
              oSession.Close()
  
              bFlag = False
          End Using
  
          MessageBox.Show("File Transfer Compelete")
  
          Return 0
      Catch ex As Exception
          MessageBox.Show(ex.ToString())
          Return 1
      End Try
  
  End Function
  
   Public Delegate Sub SetbarValues(maximum As Integer, value As Integer)
  Private Sub SessionFileTransferProgress(ByVal sender As Object, ByVal e As FileTransferProgressEventArgs)
  
  
      Dim oForm1 = Form1
      Dim msd As SetbarValues = AddressOf oForm1.sub1
  
      If oForm1.InvokeRequired Then
          msd.Invoke(1, 1)
      Else
          oForm1.sub1(1, 1)
      End If
  
      'oForm1.ProgressUpdate()
  
      'If (Form1.CheckForIllegalCrossThreadCalls) Then
      '    MsgBox("Illegal cross-thread operation deteced.")
      'End If
  
  
  End Sub
  
  Public Sub TestThread(asOption())
      Dim oSFTPConnectionManager = New SFTPConnectorManager
      Dim Thread As New Thread(AddressOf oSFTPConnectionManager.StartConnectionThread)
  
      oSFTPConnectionManager.ProtocolSelection = asOption(0)
      oSFTPConnectionManager.HostName = asOption(1)
      oSFTPConnectionManager.UserName = asOption(2)
      oSFTPConnectionManager.Port = asOption(3)
      oSFTPConnectionManager.Password = asOption(4)
      oSFTPConnectionManager.SSHKey = asOption(5)
      oSFTPConnectionManager.RemotePath = asOption(6)
      oSFTPConnectionManager.LocalPath = asOption(7)
  
      Thread.Start()
  
  End Sub
  </code></pre>
  
  <p>So you may see that I tried to use a delegate, I did a fair bit of reading on it and I believe this is what I need to update UI elements from a separate thread, but I obviously have misunderstood it because I can't implement the concept in my own project. The UI changes NEEDS to happen during the SessionFileTransferProgress event.</p>
  
  <p>Please guys and girls I am at my wits end with this, this is my final saving grace and I don't think I will be able to continue with learning to program if I can't understand and implement these concepts.</p>