在WinForm的进度条上显示WinSCP .NET程序集传输进度 [英] Showing WinSCP .NET assembly transfer progress on WinForm's progress bar
问题描述
具有一些我要从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屋!