来自单独的线程事件

时间:2016-06-29 11:31:11

标签: .net vb.net multithreading winforms winscp

我有一个名为SFTPConnectorManager.vb的类,它负责管理与服务器的FTP连接。我有Form1.vb类,它是主要的GUI。我想更新驻留在Form1上的ProgressBar以显示文件传输的进度。负责启动与FTP服务器连接的功能是在新线程上启动的,这样就不会冻结form1,这很好,但是对我来说挑战是能够更新进度条,这对于我一点都没有。

我尝试过/做过的事情:

  1. 使用委托从单独的线程更新UI
  2. 使用后台工作程序并使用它的进度更改事件,我想我可能会在这里做点什么,但后来我记得UI的更新需要在文件传输事件期间发生,特别是SessionFileTransferProgress,而不是我提出的时候进步改变了事件。
  3. 阅读有关多线程和事件处理的超过20页的文档,但我还是不明白......
  4. 我需要做什么:

    1. 更新进度条UI控件,更新WHILE正在进行文件传输,并且它不需要冻结UI,因此需要在单独的线程上运行(到目前为止我已经实现了) / LI>

      我正在使用的代码:

      1. https://winscp.net/eng/docs/library_session
      2. https://winscp.net/eng/docs/library_session_filetransferprogress
      3. 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
        

        所以你可能会看到我试图使用一个委托,我做了一些相关的阅读,我相信这是我需要从一个单独的线程更新UI元素,但我显然误解了它,因为我可以在我自己的项目中实现这个概念。 UI会在SessionFileTransferProgress事件期间更改NEEDS。

        请男孩们和女孩们以我的智慧结束这一点,这是我最后的拯救恩典,如果我无法理解并实施这些概念,我认为我不会继续学习编程。< / p>

1 个答案:

答案 0 :(得分:1)

这是一个显示概念的简单示例。它有一个类,它有一些长时间运行(sic)活动,想要向UI报告进度。您需要一个包含两个按钮,一个进度条和一个文本框的表单。希望这在概念上有所帮助。

Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ProgressBar1.Value = 0
        Dim foo As New SomeClass(New Action(AddressOf showProg))
        foo.SimulateActivity() 'long running
        Button2.Select()
    End Sub

    Public Sub showProg()
        If Me.InvokeRequired Then ' on the UI?
            Me.Invoke(Sub() showProg()) ' no, run this on the UI
        Else
            ProgressBar1.Increment(1) ' yes, on the UI
        End If
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        'test if UI available while long running
        'press button 2 while long running to confirm UI
        TextBox1.Text = ProgressBar1.Value.ToString
    End Sub
End Class

Public Class SomeClass

    Private _action As Action
    Public Sub New(progress As Action)
        Me._action = progress
    End Sub

    Public Sub SimulateActivity()
        'runs on thread
        Dim t As Task
        t = Task.Run(Sub()
                         For x As Integer = 1 To 100
                             Me._action()
                             Threading.Thread.Sleep(50)
                         Next
                     End Sub)
    End Sub
End Class
相关问题