gpt4 book ai didi

.net - vb net update UI控件来自单独的线程事件

转载 作者:行者123 更新时间:2023-12-03 13:03:58 28 4
gpt4 key购买 nike

这个问题在这里已经有了答案:





Updating GUI items upon an event raised by a thread of another class VB.nET

(1 个回答)


3个月前关闭。




我有一个名为 SFTPConnectorManager.vb 的类,它负责管理与服务器的 FTP 连接。我有 Form1.vb 类,它是主要的 GUI。我想更新 Form1 上的 ProgressBar 以显示文件传输的进度。负责与 FTP 服务器建立连接的函数在一个新线程上启动,这允许 form1 不会被卡住,这很好,但是对我来说挑战是能够更新进度条,这对我来说是行不通的我。

我尝试过/做过的事情:

  • 使用委托(delegate)从单独的线程
  • 更新 UI
  • 使用后台工作人员并使用它的进度更改事件,我想我可能会在这里做一些事情,但后来我记得 UI 的更新需要在文件传输事件期间发生,特别是 SessionFileTransferProgress,而不是当我引发进度更改事件时.
  • 阅读了超过 20 页有关多线程和事件处理的文档,我猜还是不明白...

  • 我需要发生的事情:
  • 更新进度条 UI 控件,在文件传输正在进行时更新,并且它不需要卡住 UI,因此它需要在单独的线程上运行(我相信到目前为止我已经实现了)

  • 我正在使用的代码:
  • 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

    所以你可能会看到我尝试使用委托(delegate),我对它进行了相当多的阅读,我相信这是我需要从单独的线程更新 UI 元素,但我显然误解了它,因为我无法实现我自己的项目中的概念。 UI 更改需要在 SessionFileTransferProgress 事件期间发生。

    伙计们,女孩们,我对此束手无策,这是我最后的救命之恩,如果我不能理解和实现这些概念,我认为我将无法继续学习编程。

    最佳答案

    这是一个显示概念的简单示例。它有一个类,它有一些长时间运行的(原文如此)事件,想要向 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

    关于.net - vb net update UI控件来自单独的线程事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38098298/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com