vb.net winform下载器暂停并恢复无法正常工作

时间:2016-07-23 15:51:38

标签: .net vb.net winforms

我正在尝试创建一个支持暂停和恢复功能的winform vb.net下载程序,如果在下载操作期间未单击“暂停”和“恢复”按钮,程序可以正常工作并下载文件而不会出错。但如果在下载操作期间单击暂停和继续按钮,则下载的文件将出错。如果它是一个mp3文件,它会在下载操作暂停的确切位置进行加扰(尽管它会在该点之后继续播放)。对于.zip / .rar文件,解压缩时会出现i校验和错误。我的代码:

     Imports System.ComponentModel
                Imports System.Net
                Imports System.IO
               Public Class downloadformclass

                #Region "Declarations"
                Dim whereToSave As String
                Private _filename As String
                 Private _address As String
               Public savedialogresponse As Boolean
               Delegate Sub updatesafe(size As Double, downloadposition As Integer, speed As Double, percent As Integer)
               Delegate Sub downloadstatusdelegate(value As Boolean)
               Public WithEvents BackgroundWorkers As BackgroundWorker
               Private downloadposition As Integer = 0
               Private filesize As Long = 0
               Dim j As Integer = 0
               Private totalnumberofbytesread As Integer = 0
              Private previouspositon As Long = 0
              Private previouspercent As Integer = 0
              Private previousspeed As Double = 0
              Dim canceldelegate As New downloadstatusdelegate(AddressOf downloadstatus)
              Private path As String
              Dim WithEvents k As New Dictionary(Of String, Object)
             Dim request As HttpWebRequest
             Dim response As HttpWebResponse
             Dim bannersarray As ArrayList
             Dim objMySQLConnect As New MySQLConnect
             Dim rand As New Random
             Delegate Sub safeadvertshow(objadvertbanner As Object)
           #End Region

          #Region "Overides"
           Public Overrides Function ToString() As String
           Return MyBase.Tag
         End Function
        #End Region

        #Region "Property"
    Public Property filename As String
        Get
            Return _filename
        End Get
        Set(value As String)
            _filename = value
        End Set
    End Property
    Public Property address As String
        Get
            Return _address
        End Get
        Set(value As String)
            _address = value
        End Set
    End Property
#End Region

#Region "Form events"
    Private Sub downloadformclass_Load(sender As Object, e As EventArgs) Handles Me.Load
        BackgroundWorker1.RunWorkerAsync()
        ' Timer1.Interval = 30000
        'Timer1.Start()
    End Sub
#End Region
    '   starts the background thread
#Region "Functions"
    Public Function savedialog()
        SaveFileDialog1.FileName = filename
        SaveFileDialog1.Filter = "All files (*.*)|*.*"
        SaveFileDialog1.DefaultExt = "rar"
        SaveFileDialog1.AddExtension = True
        If SaveFileDialog1.ShowDialog() = DialogResult.OK Then
            path = SaveFileDialog1.FileName
            savedialogresponse = True
            BackgroundWorkers = New BackgroundWorker
            BackgroundWorkers.WorkerSupportsCancellation = True
            AddHandler BackgroundWorkers.DoWork, AddressOf BackgroundWorker1_DoWork
            k(Tag) = BackgroundWorkers
            k(Tag).RunWorkerAsync()
            Button3.Enabled = False
        Else
            savedialogresponse = False
        End If
        Return savedialogresponse
    End Function
#End Region


#Region "Background Thread and Methods for file streaming"
    Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs)
        Dim bytesreadbuffer(4095) As Byte
        Dim numberofbytesread As Integer
        Dim percent As Integer = 0
        Dim clock As New Stopwatch
        Dim speed As Double = 0
        Dim readings As Integer = 0
        Dim downloadfile As FileStream
        bytesreadbuffer(4095) = Nothing
        j = j + 1
        If downloadposition <> 0 Then
            downloadfile = New FileStream(path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)
        Else
            downloadfile = New FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)
        End If
        Try
            request = WebRequest.Create(address)
            If downloadposition > 0 Then
                request.AddRange(downloadposition, filesize)
            Else
                request.AddRange(downloadposition)
            End If
            request.Proxy = Nothing
            request.ReadWriteTimeout = 60000
            response = request.GetResponse
        Catch ex As WebException
            MessageBox.Show("Error !!No network connection" & ex.Message)
            Me.Invoke(canceldelegate, True)
            j = 0
            Exit Sub
        End Try

        Dim safeupdate As New updatesafe(AddressOf updatelabelsandprogressbar)
        If j = 1 And downloadposition = 0 Then
            filesize = response.ContentLength
        End If
        Me.Invoke(safeupdate, filesize, downloadposition, 0, 0)

        Do
            If totalnumberofbytesread = filesize Then
                Exit Do
            End If
            If k(Tag).CancellationPending = True Then
                Exit Do
            End If
            clock.Start()
            Try
                numberofbytesread = response.GetResponseStream.Read(bytesreadbuffer, 0, 4096)
            Catch ex As Exception
                MessageBox.Show(ex.Message)
                k(Tag).CancelAsync()
            End Try
            downloadfile.Write(bytesreadbuffer, 0, numberofbytesread)
            totalnumberofbytesread = totalnumberofbytesread + numberofbytesread
            percent = (totalnumberofbytesread / filesize) * 100
            Try
                Me.Invoke(safeupdate, filesize, totalnumberofbytesread, speed, percent)
            Catch ex As Exception
                k(Tag).CancelAsync()
            End Try
            clock.Stop()
            readings = readings + 1
            If readings >= 5 Then
                speed = 20480 / (clock.ElapsedMilliseconds / 1000)
                clock.Reset()
                readings = 0
            End If
        Loop

        response.GetResponseStream.Close()
        downloadfile.Dispose()
        If k(Tag).CancellationPending = True Then
            Try
                downloadposition = totalnumberofbytesread
                Me.Invoke(canceldelegate, True)
            Catch ex As Exception
                File.Delete(path)
                Exit Sub
            End Try
            Exit Sub
        End If
        Me.Invoke(canceldelegate, False)
    End Sub

    Public Sub downloadstatus(d As Boolean)
        If d = True Then
            Button3.Enabled = True
            Button2.Enabled = False
            MessageBox.Show("download paused")
        Else
            Button3.Enabled = False
            Button2.Enabled = False
            MessageBox.Show("download complete")
        End If
    End Sub

    Private Sub updatelabelsandprogressbar(size As Long, downloadposition As Long, speed As Double, percent As Integer)
        Try
            Me.Refresh()
            Label1.Text = "Progress : " & percent & "%"
            Label2.Text = "Downloaded:" & downloadposition & " KB of " & size & "KB"
            Label3.Text = "Speed: " & Math.Round((speed / 1024), 2) & " KB/s"
            ProgressBar1.Value = percent
        Catch ex As Exception
            MessageBox.Show("An Error occured: " & ex.Message)
        End Try
    End Sub

#End Region


#Region "Button Clicks event"
    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        request.Abort()
    End Sub

    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        k(Tag).RunWorkerAsync()
        Button3.Enabled = False
        Button2.Enabled = True
    End Sub



#End Region

#Region "Timer events/advert"
    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        Try
            '   BackgroundWorker1.RunWorkerAsync()
        Catch ex As Exception
            ''  MessageBox.Show("hanging because we r busy")
        End Try
    End Sub

    Private Sub BackgroundWorker_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Dim objadvertbanner As New advertbannerclass
        bannersarray = New ArrayList
        ' bannersarray = MySQLConnect.getadvertbanners
        ' objadvertbanner = bannersarray(rand.Next(0, 1)) 'bannersarray.Count
        Dim objsafeadvertshow As New safeadvertshow(AddressOf advertshow)
        Me.Invoke(objsafeadvertshow, objadvertbanner)
    End Sub

    Public Sub advertshow(objadvertbanner As Object)
        If objadvertbanner.bannerpath = "waitingforaddress" Then
            PictureBox1.Image = My.Resources.loading
            PictureBox1.Tag = Nothing
            PictureBox1.Cursor = Cursors.Default
        Else
            Try
                PictureBox1.Load(objadvertbanner.bannerpath)
                PictureBox1.Tag = objadvertbanner.bannerurllink
                If PictureBox1.Tag = Nothing Then
                    PictureBox1.Cursor = Cursors.Default
                Else
                    PictureBox1.Cursor = Cursors.Hand
                End If
            Catch ex As Exception
                PictureBox1.Image = Nothing
                PictureBox1.Tag = Nothing
            End Try
        End If
    End Sub
    Private Sub PictureBox1_Click(sender As Object, e As EventArgs) Handles PictureBox1.Click
        Try
            Process.Start(sender.Tag.ToString)
        Catch ex As Exception
        End Try
    End Sub
#End Region

End Class

Screenshot

1 个答案:

答案 0 :(得分:0)

终于找到了解决方案,它现在按预期工作,我添加了代码:

        numberofbytesread = numberofbytesread - numberofbytesread

到catch块内的do循环。单击暂停按钮时,&#34;请求&#34;如button2.click事件中所示中止。但是当发生这种情况时,它很可能会尝试将数据读入缓冲区,所以我发现这个缓冲区中包含的数据会因点击暂停按钮而被破坏。因此代码&#34; numberofbytesread = numberofbytesread - numberofbytesread&#34;确保在请求终止时不会将任何内容写入文件流。完整的do循环代码是:

         Do
        If totalnumberofbytesread = filesize Then
            Exit Do
        End If
        If k(Tag).CancellationPending = True Then
            Exit Do
        End If
        clock.Start()
        Try
            numberofbytesread =          response.GetResponseStream.Read(bytesreadbuffer, 0, 4096)
        Catch ex As Exception
            MessageBox.Show(ex.Message)
            k(Tag).CancelAsync()
            numberofbytesread = numberofbytesread - numberofbytesread
        End Try
        downloadfile.Write(bytesreadbuffer, 0, numberofbytesread)
        totalnumberofbytesread = totalnumberofbytesread + numberofbytesread
        percent = (totalnumberofbytesread / filesize) * 100
        Try
            Me.Invoke(safeupdate, filesize, totalnumberofbytesread, speed, percent)
        Catch ex As Exception
            k(Tag).CancelAsync()
        End Try
        clock.Stop()
        readings = readings + 1
        If readings >= 5 Then
            speed = 20480 / (clock.ElapsedMilliseconds / 1000)
            clock.Reset()
            readings = 0
        End If
    Loop