有一些主要表单,我从FTP调用文件下载。当我提出这个操作时,我希望看到新的表单ShowDialog
和它上面的进度条同时显示,然后显示进度并关闭新表单并返回主表单。然而,我的代码正在工作,当它将处理时,我的主窗体冻结,然后在新窗体出现然后关闭时。我想纠正的是显示这个新表格在执行过程后立即显示。你能看看并告诉我什么是错的吗?
这是我的主要形式下载过程:
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我自己的类并使用了方法:
...
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
...
进一步讨论nr 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()
在其他一些类中(也许在此方法被放入不同类之前未提及 - 我的自定义类)
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
答案 0 :(得分:1)
这意味着它只在转移完成后返回。
解决方案是:
在单独的线程中运行WinSCP传输(Session.GetFiles
),而不是阻止GUI线程。
请参阅WinForm Application UI Hangs during Long-Running Operation
处理Session.FileTransferProgress
event。
虽然请注意事件处理程序将在后台线程上调用,因此您无法直接从处理程序更新进度条。您必须使用Control.Invoke
来确保在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
如果您想阻止用户进行某些操作,您可能希望在操作期间禁用进度表单(或其部分)。
使用表单或控件的.Enabled
属性。
更容易,但是hacky且通常不推荐的解决方案是从现有的Application.DoEvents
处理程序中调用SessionFileTransferProgress
方法。
当然,您还必须从SessionFileTransferProgress
更新进度条。
Private Shared Sub SessionFileTransferProgress(sender As Object, e As FileTransferProgressEventArgs)
'Print transfer progress
ProgressBar1.Value = e.FileProgress
Application.DoEvents
End Sub
进度条的.Minimum
和.Maximum
必须在Session.GetFiles
之前设置。
但不要那样做!这是一种错误的做法。
然而,您需要以与上述正确解决方案相同的方式禁用表单/控件。