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.
What I have tried/done:
- Using a delegate to update the UI from the separate thread
- 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.
- Read well over 20 pages worth of documentation in regards to multi-threading and event handling, still don't understand it I guess...
What I need to happen:
- 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)
Code I am using:
- https://winscp.net/eng/docs/library_session
- https://winscp.net/eng/docs/library_session_filetransferprogress
Form1.vb
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) <> 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)
SFTPConnectorManager.vb
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
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.
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.