2016-07-23 77 views
0

我想创建一个支持暂停和恢复功能的winform vb.net下载程序,该程序工作正常,并下载文件没有错误,如果“暂停”和“简历“按钮在下载操作过程中不会被点击。但如果在下载操作过程中单击了暂停和恢复按钮,则下载的文件会出现错误。如果它是一个mp3文件,它会在下载操作暂停的确切点上加扰(尽管它在该点之后继续播放)。为.zip/.rar文件我解压缩时出现校验错误。我的代码:vb.net winform下载暂停和恢复不能正常工作

 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

+0

首先,使用[选项严格开](https://msdn.microsoft.com/en-us/library/zcd4xwzs.aspx)并纠正它显示的问题。这可能会使你的程序正常工作,但如果没有,那么请使用正确的代码编辑你的问题,并明确指出什么不起作用。 –

+0

@安德鲁莫顿我试过严格的选项,没有问题要纠正。就像我说的那样,程序工作正常,并且它没有错误地下载任何文件(当暂停n恢复按钮没有被点击时)。然而,当我在下载操作过程中点击暂停和恢复按钮时,下载的文件就会出现错误 –

+0

您对Option Strict On的使用必须有一个问题:它应该指出(至少)'Process.Start( sender.Tag.ToString)'因为'Tag'不是Object的一个属性。我建议你在'Imports'语句之前的行上加上'Option Strict On'。 –

回答

0

终于找到了解决办法,现在按预期工作,我加入了代码:

 numberofbytesread = numberofbytesread - numberofbytesread 

在做循环,catch块内。当点击暂停按钮时,“请求”将在button2.click事件中看到中止。但是当这种情况发生时,它很可能会尝试将数据读入缓冲区,所以我发现由于单击暂停按钮而导致缓冲区中包含的数据将被损坏。因此,代码“numberofbytesread = numberofbytesread - numberofbytesread”确保在请求终止时没有任何内容写入文件流。完整的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 
+0

你知道这么做︰'numberofbytesread = numberofbytesread - numberofbytesread' _ **是完全一样的** _作为:'numberofbytesread = 0',对吧? –

+0

@VisualVincent是的,我应该刚刚做到了这一点。无论如何,它可以防止当请求被中止写入文件流时,“读取”字节的损坏块。我已经测试过它,它的工作 –