在WinForm的进度条上显示WinSCP .NET程序集传输进度 [英] Showing WinSCP .NET assembly transfer progress on WinForm's progress bar

查看:135
本文介绍了在WinForm的进度条上显示WinSCP .NET程序集传输进度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

具有一些我要从FTP下载文件的主要形式.进行此操作时,我想将新表格显示为ShowDialog,同时在其上显示进度条,然后显示进度并关闭新表格并返回主表格.但是,我的代码正在运行,当它开始处理时,我的主窗体冻结,而在新窗体出现然后关闭时,我的主窗体冻结了.我要纠正的是,要显示此新表格在执行过程后立即显示出来.你能看看我怎么了吗?

Have some main form on which I am calling file downloading from FTP. When this operation is raised i want to see new form as ShowDialog and progress bar on it to be shown meantime, then show the progress and close new form and back to main form. My code is working however, when it will process is started my main form freezes and after while new form is appearing and then closing. What I would like to correct is to show this new form to be showed straightaway after process is executed. Can you take a look and tell me whats wrong?

这是我下载程序的主要形式:

This is out of my main form the download process called:

Dim pro As New FrmProgressBarWinscp(WinScp, myremotePicturePath, ladujZdjeciaPath, True)

FrmProgressBarWinscp如下:

Public Class FrmProgressBarWinscp

    Property _winScp As WinScpOperation
    Property _remotePicture As String
    Property _ladujZdjecia As String
    Property _removesource As String

    Public Sub New()
        InitializeComponent()
    End Sub

    Sub New(winscp As WinScpOperation, remotePicture As String, ladujzdjecia As String, removesource As Boolean)
        ' This call is required by the designer.
        InitializeComponent()
        ' Add any initialization after the InitializeComponent() call.
        _winScp = winscp
        _remotePicture = remotePicture
        _ladujZdjecia = ladujzdjecia
        _removesource = removesource
        ShowDialog()
    End Sub

    Sub Run()

        Try
            Cursor = Cursors.WaitCursor
            _winScp.GetFile(_remotePicture, _ladujZdjecia, _removesource)
            ProgressBar1.Minimum = 0
            ProgressBar1.Maximum = 1
            ProgressBar1.Value = 0
            Do
                ProgressBar1.Value = WinScpOperation._lastProgress
                ProgressBar1.Refresh()
            Loop Until ProgressBar1.Value = 1
            Cursor = Cursors.Default
            'Close()

        Catch ex As Exception

        Finally
            If _winScp IsNot Nothing Then
                _winScp.SessionDispose()
            End If

            System.Threading.Thread.Sleep(10000)
            Close()
        End Try

    End Sub

    Private Sub FrmProgressBarWinscp_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Run()
    End Sub
End Class

Winscp我自己的类和使用的方法:

Winscp my own class and used methods:

...
Function GetFile(source As String, destination As String, Optional removeSource As Boolean = False)
    Dim result As Boolean = True
    Try

        session.GetFiles(source, destination, removeSource).Check()

    Catch ex As Exception
        result = False
    End Try
    Return result
End Function

Private Shared Sub SessionFileTransferProgress(sender As Object, e As FileTransferProgressEventArgs)
    'Print transfer progress
    _lastProgress = e.FileProgress

End Sub

Public Shared _lastProgress As Integer

...

进一步讨论3:

Main form:
 Dim tsk As Task(Of Boolean) = Task.Factory.StartNew(Of Boolean)(Function()
                                                                                                Return WinScp.GetFile(myremotePicturePath, ladujZdjeciaPath, True)

                                                                                            End Function)


                            Dim forma As New FrmProgressBar
                            forma.ShowDialog()

进度栏形式:

Public Class FrmProgressBar

    Public Sub New()
        InitializeComponent()
    End Sub
    Sub Run()
        Try
            Do
                ProgressBar1.Value = WinScpOperation._lastProgress
                ProgressBar1.Refresh()
            Loop Until ProgressBar1.Value = 1
            Cursor = Cursors.Default

        Catch ex As Exception
        Finally
            MsgBox("before sleep")
            System.Threading.Thread.Sleep(10000)
            MsgBox("after sleep sleep")
            Close()
        End Try
    End Sub

    Private Sub FrmProgressBarWinscp_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Run()
    End Sub
End Class

点数nr. 4:

  Dim tsk As Task(Of Boolean) = Task.Factory.StartNew(Of Boolean)(Function()
                                                                                                Return WinScp.GetFile(myremotePicturePath, ladujZdjeciaPath, True)

                                                                                            End Function)


                            Dim pic As New Waiting
                            pic.ShowDialog()

                            Task.WaitAll(tsk)
                            pic.Close()

第5点:

 Dim pic As New Waiting
                            pic.ShowDialog()
                            Dim tsk As Task = Task.Factory.StartNew(Sub() WinScp.GetFile(myremotePicturePath, ladujZdjeciaPath, pic, True))




                            Task.WaitAll(tsk)
                            'pic.Close()

在其他一些类中(可能没有在将此方法放入其他类中之前提到过-我的自定义类)

In some other class (maybe didn't mentioned before this method is placed in diffrent class - my custom one)

Public Function GetFile(source As String, destination As String, formclose As InvokeCloseForm, Optional removeSource As Boolean = False) As Boolean
        Dim result As Boolean = True
        Try
            session.GetFiles(source, destination, removeSource).Check()
        Catch ex As Exception
            result = False
        End Try
        formclose.RUn()
        Return result
    End Function

接口:

Public Interface InvokeCloseForm
    Sub RUn()
End Interface

等待表格:

Public Class Waiting
    Implements InvokeCloseForm

    Public Sub RUn() Implements InvokeCloseForm.RUn
        Me.Close()
    End Sub
End Class

推荐答案

Session.GetFiles方法处于阻止状态.

The Session.GetFiles method in blocking.

这意味着它仅在传输完成后返回.

It means it returns only after the transfer finishes.

解决方案是:

  • 在单独的线程中运行WinSCP传输(Session.GetFiles),而不是阻塞GUI线程.

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

有关该信息,请参见 WinForm应用程序UI在长时间运行过程中挂起

处理 Session.FileTransferProgress事件.

尽管请注意,事件处理程序将在后台线程上调用,所以您不能直接从处理程序中更新进度条.您必须使用Control.Invoke来确保进度条在GUI线程上已更新.

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.

为此,请参见如何从C#中的另一个线程更新GUI?

一个简单的实现就像:

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.

    使用表单或控件的.Enabled属性.

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

    更简单但又不推荐使用的解决方案是从您现有的SessionFileTransferProgress处理程序中调用Application.DoEvents方法.

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

    当然,您还必须从SessionFileTransferProgress更新进度条.

    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
    

    并且必须在Session.GetFiles之前设置进度条的.Minimum.Maximum.

    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.

    这篇关于在WinForm的进度条上显示WinSCP .NET程序集传输进度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆