Showing WinSCP .NET assembly transfer progress on WinForm's progress bar

非 Y 不嫁゛ 提交于 2019-12-01 13:51:23
Martin Prikryl

The Session.GetFiles method in blocking.

It means it returns only after the transfer finishes.

The solution is to:

  • Run the WinSCP transfer (the Session.GetFiles) in a separate thread, not to block the GUI thread.

    For that see WinForm Application UI Hangs during Long-Running Operation

  • Handle the Session.FileTransferProgress event.

    Though note that the event handler will be called on the background thread, so you cannot update the progress bar directly from the handler. You have to use the Control.Invoke to make sure the progress bar is updated on the GUI thread.

    For that see How to update the GUI from another thread in C#?

  • A trivial implementation is like:

    Public Class ProgressDialog1
    
        Private Sub ProgressDialog1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ' Run download on a separate thread
            ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf Download))
        End Sub
    
        Private Sub Download(stateInfo As Object)
            ' Setup session options
            Dim mySessionOptions As New SessionOptions
            With mySessionOptions
                ... 
            End With
    
            Using mySession As Session = New Session
                AddHandler mySession.FileTransferProgress, AddressOf SessionFileTransferProgress
    
                ' Connect
                mySession.Open(mySessionOptions)
    
                mySession.GetFiles(<Source>, <Destination>).Check()
            End Using
    
            ' Close form (invoked on GUI thread)
            Invoke(New Action(Sub() Close()))
        End Sub
    
        Private Sub SessionFileTransferProgress(sender As Object, e As FileTransferProgressEventArgs)
            ' Update progress bar (on GUI thread)
            ProgressBar1.Invoke(New Action(Of Double)(AddressOf UpdateProgress), e.OverallProgress)
        End Sub
    
        Private Sub UpdateProgress(progress As Double)
            ProgressBar1.Value = progress * 100
        End Sub
    End Class
    
  • You may want to disable the progress form (or its parts) during the operation, if you want to prevent the user from doing some operations.

    Use the .Enabled property of the form or control(s).


Easier, but hacky and generally not recommendable solution, is to call the Application.DoEvents method from your existing SessionFileTransferProgress handler.

And of course, you have to update the progress bar from the the SessionFileTransferProgress as well.

Private Shared Sub SessionFileTransferProgress(sender As Object, e As FileTransferProgressEventArgs)
    'Print transfer progress
    ProgressBar1.Value = e.FileProgress
    Application.DoEvents
End Sub

And the progress bar's .Minimum and .Maximum must be set before the Session.GetFiles.

But do not do that! That's a wrong approach.

And still, you need to disable the forms/controls the same way as in the correct solution above.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!