使用backgroundworker下载文件

时间:2014-07-16 06:36:42

标签: vb.net backgroundworker downloadfile

我想通过使用backgroundworker下载两个zip文件,但是当我想下载文件时,它给我一个错误,即背景工作者很忙并且不能同时运行多个任务。这是代码

Imports System.Net
Public Class mainForm

Dim whereToSave As String 'Where the program save the file
Private files() As String = {}
Private dlCount As Integer = 0
Delegate Sub ChangeTextsSafe(ByVal length As Long, ByVal position As Integer, ByVal percent As Integer, ByVal speed As Double)
Delegate Sub DownloadCompleteSafe(ByVal cancelled As Boolean)

Public Sub DownloadComplete(ByVal cancelled As Boolean)
    'Me.txtFileName.Enabled = True
    Me.btnDownload.Enabled = True
    Me.btnCancel.Enabled = False

    If cancelled Then

        Me.Label4.Text = "Cancelled"

        MessageBox.Show("Download aborted", "Aborted", MessageBoxButtons.OK, MessageBoxIcon.Information)


    Else
        Me.Label4.Text = "Successfully downloaded"

        MessageBox.Show("Successfully downloaded!", "All OK", MessageBoxButtons.OK, MessageBoxIcon.Information)


    End If

    Me.ProgressBar1.Value = 0
    'Me.Label5.Text = "Downloading: "
    'Me.Label6.Text = "Save to: "
    'Me.Label3.Text = "File size: "
    'Me.Label2.Text = "Download speed: "
    Me.Label4.Text = ""

End Sub

单击“下载”按钮

   Private Sub btnDownload_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDownload.Click
    Me.btnDownload.Enabled = False
    Me.btnCancel.Enabled = True
    Dim TestString As String = "http://ec2-54-76-30-19.eu-west-1.compute.amazonaws.com/manapps/IDGo800_Minidriver_32.zip," & _
       "http://ec2-54-76-30-19.eu-west-1.compute.amazonaws.com/manapps/IDGo800_Minidriver_64.zip"
    Dim strFile As String
    Dim length As Long
    Dim position As Integer
    Dim percent As Integer
    Dim speed As Double
    files = TestString.Split(CChar(","))
    Dim a As String

    For Each a In files
        Dim b() As String = a.Split("/"c)
        strFile = b(b.Length - 1)
        'Dim strFileName As String = ""
        'MsgBox(a)
        'MsgBox(strFile)

        Me.whereToSave = "C:\Temp\" & strFile
        Me.DownloadingLabel.Text = "Downloading: " & strFile
        Me.SaveToLabel.Text = "Save To: " & strFile
        Me.FileSizeLabel.Text = "File Size: " & Math.Round((length / 1024), 2) & " KB"
        Me.Label4.Text = "Downloaded " & Math.Round((position / 1024), 2) & " KB of " & Math.Round((length / 1024), 2) & "KB (" & Me.ProgressBar1.Value & "%)"
        If speed = -1 Then
            Me.DownloadSpeedLabel.Text = "Speed: calculating..."
        Else
            Me.DownloadSpeedLabel.Text = "Speed: " & Math.Round((speed / 1024), 2) & " KB/s"
        End If
        Me.ProgressBar1.Value = percent
        dlCount = 0
        StartDownload()
    Next

End Sub

调用下载功能

Private Sub StartDownload()
    dlCount += 1
    If dlCount <= files.Length Then
        BackgroundWorker1.RunWorkerAsync(files(dlCount - 1))
    Else
        MessageBox.Show("All files Downloaded")
        'Button1.Enabled = True
    End If
End Sub

BackgroundWorker的

Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    Dim arg As String = DirectCast(e.Argument, String)
    'Creating the request and getting the response
    Dim theResponse As HttpWebResponse
    Dim theRequest As HttpWebRequest
    Try 'Checks if the file exist

        theRequest = WebRequest.Create(arg)
        theResponse = theRequest.GetResponse
    Catch ex As Exception

        MessageBox.Show("An error occurred while downloading file. Possibe causes:" & ControlChars.CrLf & _
                        "1) File doesn't exist" & ControlChars.CrLf & _
                        "2) Remote server error", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Exit Sub
    End Try
End Sub

如果完成,则会调用backgroundcomplete

Private Sub bgw_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    StartDownload()
End Sub

3 个答案:

答案 0 :(得分:0)

您的代码看起来似乎正确 添加此代码,然后重试If Not Me.BGWorkerTwo.IsBusy Then Me.BGWorkerTwo.RunWorkerAsync()

答案 1 :(得分:0)

vb.net不太好用。但为什么不使用任务。我认为他们更适合这种行为。

Sub Main()


    Task.Factory.StartNew(Function() DownloadFile())


End Sub

Private Sub DownloadFile()
    Dim webClient1 As New WebClient()
    webClient1.DownloadFile("htt:\\one.two.three.com\file", "something.txt")
End Sub

可以同时下载所有文件。

答案 2 :(得分:-1)

导入System.Net 公共类mainForm

Dim whereToSave As String 'Where the program save the file

Delegate Sub ChangeTextsSafe(ByVal length As Long, ByVal position As Integer, ByVal percent As Integer, ByVal speed As Double)
Delegate Sub DownloadCompleteSafe(ByVal cancelled As Boolean)

Public Sub DownloadComplete(ByVal cancelled As Boolean)
    Me.txtFileName.Enabled = True
    Me.btnDownload.Enabled = True
    Me.btnCancel.Enabled = False

    If cancelled Then

        Me.Label4.Text = "Cancelled"

        MessageBox.Show("Download aborted", "Aborted", MessageBoxButtons.OK, MessageBoxIcon.Information)


    Else
        Me.Label4.Text = "Successfully downloaded"

        MessageBox.Show("Successfully downloaded!", "All OK", MessageBoxButtons.OK, MessageBoxIcon.Information)


    End If

    Me.ProgressBar1.Value = 0
    Me.Label5.Text = "Downloading: "
    Me.Label6.Text = "Save to: "
    Me.Label3.Text = "File size: "
    Me.Label2.Text = "Download speed: "
    Me.Label4.Text = ""

End Sub

Public Sub ChangeTexts(ByVal length As Long, ByVal position As Integer, ByVal percent As Integer, ByVal speed As Double)

    Me.Label3.Text = "File Size: " & Math.Round((length / 1024), 2) & " KB"

    Me.Label5.Text = "Downloading: " & Me.txtFileName.Text

    Me.Label4.Text = "Downloaded " & Math.Round((position / 1024), 2) & " KB of " & Math.Round((length / 1024), 2) & "KB (" & Me.ProgressBar1.Value & "%)"

    If speed = -1 Then
        Me.Label2.Text = "Speed: calculating..."
    Else
        Me.Label2.Text = "Speed: " & Math.Round((speed / 1024), 2) & " KB/s"
    End If

    Me.ProgressBar1.Value = percent


End Sub

Private Sub btnDownload_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDownload.Click

    If Me.txtFileName.Text <> "" AndAlso Me.txtFileName.Text.StartsWith("http://") Then


        Me.SaveFileDialog1.FileName = TextBox1.Text

        If Me.SaveFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then

            Me.whereToSave = Me.SaveFileDialog1.FileName

            Me.SaveFileDialog1.FileName = ""

            Me.Label6.Text = "Save to: " & Me.whereToSave

            Me.txtFileName.Enabled = False
            Me.btnDownload.Enabled = False
            Me.btnCancel.Enabled = True

            Me.BackgroundWorker1.RunWorkerAsync() 'Start download

        End If

    Else

        MessageBox.Show("Please insert valid URL for download", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning)

    End If

End Sub

Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork

    'Creating the request and getting the response
    Dim theResponse As HttpWebResponse
    Dim theRequest As HttpWebRequest
    Try 'Checks if the file exist

        theRequest = WebRequest.Create(Me.txtFileName.Text)
        theResponse = theRequest.GetResponse
    Catch ex As Exception

        MessageBox.Show("An error occurred while downloading file. Possibe causes:" & ControlChars.CrLf & _
                        "1) File doesn't exist" & ControlChars.CrLf & _
                        "2) Remote server error", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)

        Dim cancelDelegate As New DownloadCompleteSafe(AddressOf DownloadComplete)

        Me.Invoke(cancelDelegate, True)

        Exit Sub
    End Try
    Dim length As Long = theResponse.ContentLength 'Size of the response (in bytes)

    Dim safedelegate As New ChangeTextsSafe(AddressOf ChangeTexts)
    Me.Invoke(safedelegate, length, 0, 0, 0) 'Invoke the TreadsafeDelegate

    Dim writeStream As New IO.FileStream(Me.whereToSave, IO.FileMode.Create)

    'Replacement for Stream.Position (webResponse stream doesn't support seek)
    Dim nRead As Integer

    'To calculate the download speed
    Dim speedtimer As New Stopwatch
    Dim currentspeed As Double = -1
    Dim readings As Integer = 0

    Do

        If BackgroundWorker1.CancellationPending Then 'If user abort download
            Exit Do
        End If

        speedtimer.Start()

        Dim readBytes(4095) As Byte
        Dim bytesread As Integer = theResponse.GetResponseStream.Read(readBytes, 0, 4096)

        nRead += bytesread
        Dim percent As Short = (nRead * 100) / length

        Me.Invoke(safedelegate, length, nRead, percent, currentspeed)

        If bytesread = 0 Then Exit Do

        writeStream.Write(readBytes, 0, bytesread)

        speedtimer.Stop()

        readings += 1
        If readings >= 5 Then 'For increase precision, the speed it's calculated only every five cicles
            currentspeed = 20480 / (speedtimer.ElapsedMilliseconds / 1000)
            speedtimer.Reset()
            readings = 0
        End If
    Loop

    'Close the streams
    theResponse.GetResponseStream.Close()
    writeStream.Close()

    If Me.BackgroundWorker1.CancellationPending Then

        IO.File.Delete(Me.whereToSave)

        Dim cancelDelegate As New DownloadCompleteSafe(AddressOf DownloadComplete)

        Me.Invoke(cancelDelegate, True)

        Exit Sub

    End If

    Dim completeDelegate As New DownloadCompleteSafe(AddressOf DownloadComplete)

    Me.Invoke(completeDelegate, False)

End Sub

Private Sub mainForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Me.Label4.Text = ""
End Sub

Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
    Me.BackgroundWorker1.CancelAsync() 'Send cancel request
End Sub


End Class