FTP download thread locking GUI

0 votes
asked Nov 13, 2012 by gwolf2u (480 points)
edited Nov 14, 2012

Hello, I have an issues with the FTP control Currently downloaded the trial version to test out if I should buy it or not and pretty far am impressed but however I have a question. It seems that my form is freezing when downloading. Am aware that this is because of the thread the download runs, but am not sure how to control this and not to make it freeze.

Below is my code (buttons are custom controls also progress bar but the rest is same normal stuff)

    Imports Rebex
Imports Rebex.IO
Imports Rebex.Net
Imports Rebex.Security.Certificates

Public Class Form1
    Private FTP As Ftp
    Dim ip As String = "my ip"
    Dim port As Integer = "21"
    Dim username As String = "username"
    Dim password As String = "pass"
    Dim ssltrue As Rebex.Net.SslMode = SslMode.Explicit

    Private Sub ButtonGreen1_Click(sender As System.Object, e As System.EventArgs) Handles ButtonGreen1.Click
        Download()
    End Sub

    Public Sub Download()
        If Not Connect() Then
            Return
        End If

        Try
            FTP.Download("path_server", "download", TraversalMode.Recursive, TransferMethod.Copy, ActionOnExistingFiles.OverwriteDifferentSize)
        Catch ex As Exception
            MsgBox(ex.Message)
        Finally
            Disconnect()
        End Try
    End Sub

    Private Sub TransferProgressChanged(ByVal sender As Object, ByVal e As FtpTransferProgressChangedEventArgs)
        PreloaderProgressBar1.Progress = e.ProgressPercentage
        Label3.Text = "Total files " & e.FilesTotal
        Label4.Text = "Files processed " & e.FilesProcessed
        Label5.Text = "Speed " & ThreeNonZeroDigits(BytesTO(e.BytesPerSecond, convTo.KB)) & " KB\s"
        Label6.Text = "Total downloaded " & ThreeNonZeroDigits(BytesTO(e.BytesTransferred, convTo.MB)) & " MB"
        If PreloaderProgressBar1.Progress = 100 Then
            ButtonGreen1.Text = "Start Download"
        Else
            ButtonGreen1.Text = "Downloading..."
        End If
Application.DoEvents()
    End Sub

    Private Sub ButtonBlue1_Click(sender As System.Object, e As System.EventArgs) Handles ButtonBlue1.Click
        Me.Close()
    End Sub

    Private Function Connect() As Boolean
        Try
            Cursor = Cursors.WaitCursor

            FTP = New Ftp
            FTP.Settings.SslAcceptAllCertificates = True
            Dim passive As Boolean = CheckBox1.Checked
            FTP.Passive = passive
            Dim largebuffers As Boolean = CheckBox2.Checked

            FTP.LogWriter = New Rebex.FileLogWriter(Application.StartupPath & "\connection_log.log", Rebex.LogLevel.Debug)

            FTP.Settings.UseLargeBuffers = largebuffers
            FTP.Connect(ip, port, ssltrue)
            FTP.Login(username, password)

            AddHandler FTP.TransferProgressChanged, AddressOf TransferProgressChanged
            Return True
        Catch x As Exception
            MsgBox(x)
            Return False
        Finally
            Cursor = Cursors.Arrow
        End Try
    End Function

    Private Sub Disconnect()
        FTP.Disconnect()
        FTP.Dispose()
        FTP = Nothing
    End Sub
End Class

Now how can I prevent this freezing?

1 Answer

+1 vote
answered Nov 14, 2012 by Pavel Matyska (13,340 points)
edited Nov 14, 2012
 
Best answer

Hi, to prevent freezing GUI it is recomennded to use asynchronous variaiton of download operation.

If you are on .net 4.5, just switch the line:

FTP.Download("path_server", "download", ...)

to

await FTP.DownloadAsync("path_server", "download", ...)

and make the Download metod async with async key word. Also remove the Application.DoEvents call from the TransferProgressChanged handler.

This will await for asynchronous download.

If you are on .net 4.0, it is not such simple, but achievable. I suggest you to alter Download method like this:

 Private Sub Download()
    If Not Connect() Then
        Return
    End If

    Try
        FTP.DownloadAsync("path_server", "download", TraversalMode.Recursive, TransferMethod.Copy, ActionOnExistingFiles.OverwriteDifferentSize).ContinueWith(AddressOf Disconnect)
    Catch ex As Exception ''# this exception occurs before the asynchronous operation started.
        MessageBox.Show(ex.Message)
        Disconnect()
    End Try
End Sub

And add overloaded Disconnect method with Task parameter like this:

Private Sub Disconnect(ByVal operation As Task)
    If operation.IsFaulted Then
        MessageBox.Show(operation.Exception.ToString())
    ElseIf operation.IsCanceled Then ''# this is set when the download was aborted by FTP.Abort() call.
        MessageBox.Show("Download was canceled.")
    End If

    Disconnect()
End Sub

And also remove the Application.DoEvents call.

If you are on earlier version of .net framework, let us know.

commented Nov 14, 2012 by gwolf2u (480 points)
edited Nov 14, 2012

thanks a lot cheers

...