1

好的,所以我一直在尝试用不同的方法下载一个大文件。在我的代码中,通常效果最好的是My.Computer.NetWork.DownloadFile,但由于文件是 1.5Gb,我的 windows 窗体冻结并且没有响应。在我等了 5 分钟后,我没有费心去看看它多久没有响应,因为我认为这只是浪费时间。所以我也尝试过wc.DownloadFileAsync(wc 代表 Web 客户端)它可以工作并且不会冻结我的 Windows 窗体,但问题是它会跳过它并且不会等到下载完成所以它会继续使用我的代码和因此我得到错误。

我尝试研究在下载完成之前暂停或停止代码的方法,但没有运气。经过进一步的研究,我发现了 backgroundworker 类。我想知道这是否对我有用,我将如何在我的代码中实现它,或者是否有更简单的方法可以做到这一点?

我无法成功地将它实现到我的代码中。我无法调用,因此出现如下错误:Cross-thread operation not valid.

这是目前我的代码,后台工作人员:

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

    Dim downloader As New System.Net.WebClient

    Dim ServerVersion = wc.DownloadString("http://127.0.0.1:8080/patch/PatchList.txt").Trim
    Dim tLines As String() = ServerVersion.Split(Environment.NewLine)
    For Each NewLine As String In tLines
        Dim tVersionAndUrl As String() = NewLine.Split(vbTab)

        Dim encText As New System.Text.UTF8Encoding()
        Dim btText() As Byte
        btText = encText.GetBytes(tVersionAndUrl(0))
        'MessageBox.Show(btText.ToString)

        'MessageBox.Show(tVersionAndUrl(0)(0))
        If tVersionAndUrl.Length < 2 Then
            Exit For
        End If
        If Integer.Parse(tVersionAndUrl(0)) < Integer.Parse(CVersion.Text) Then
            Dim TempPath As String = "\launcher\temp.rar"

            AddHandler wc.DownloadProgressChanged, AddressOf ProgressChanged
            AddHandler wc.DownloadProgressChanged, AddressOf ProgressChanged
            AddHandler wc.DownloadFileCompleted, AddressOf DownloadCompleted
            'wc.DownloadFileAsync(New Uri(tVersionAndUrl(1)), Me.GetFileName(tVersionAndUrl(1)))
            wc.DownloadFileAsync(New Uri(tVersionAndUrl(1)), tmp, Stopwatch.StartNew)
            'My.Computer.FileSystem.DeleteFile(Me.GetFileName(tVersionAndUrl(1)))


            CVersion.Text = tVersionAndUrl(0)
            LabelStatus.Text = "Download in Progress"
            Button1.Enabled = False

        End If
    Next
    MsgBox("Client is up to date")

End Sub

这是它的 Addhandlers:

    Private Sub ProgressChanged(ByVal sender As Object, ByVal e As DownloadProgressChangedEventArgs)
    Dim bytesIn As Double = Double.Parse(e.BytesReceived.ToString())
    Dim totalBytes As Double = Double.Parse(e.TotalBytesToReceive.ToString())
    Dim percentage As Double = bytesIn / totalBytes * 100
    ProgressBarCurrent.Value = Int32.Parse(Math.Truncate(percentage).ToString())

    Dim BytesDownloaded As String = (e.BytesReceived / (DirectCast(e.UserState, Stopwatch).ElapsedMilliseconds / 1000.0#)).ToString("#")

    If BytesDownloaded < 1024 Then
        Dim Bs As String = Convert.ToInt32(BytesDownloaded)
        Label4.Text = (Bs & " B/s")
    ElseIf BytesDownloaded < 1048576 Then
        Dim KBs As String = Math.Round(BytesDownloaded / 1024, 2)
        Label4.Text = (KBs & " KB/s")
    ElseIf BytesDownloaded < 1073741824 Then
        Dim MBs As String = Math.Round(BytesDownloaded / 1048576, 2)
        Label4.Text = (MBs & " MB/s")
    End If

End Sub

Private Sub DownloadCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs)
    'MessageBox.Show("Download Complete")
    LabelStatus.Text = "Download Complete"
    Button1.Enabled = True
    Downloading = False
End Sub

我将不胜感激任何帮助。谢谢。

4

2 回答 2

0

在您的代码中,我们可以看到您使用了 BackgroundWorker 类,这对我来说似乎很好。我试图找到的是 BackgroundWorker 类的剩余委托函数,如ProgressChangedRunWorkerCompleted(相反,您已经注册了自己的委托,这可能会导致后期出现错误)。尝试处理这些事件,它应该对您有所帮助,并让您知道任务何时完成并同时报告进度。为了报告进度,在主 UI 线程中,您还可以运行style属性设置为的进度条Marquee

于 2013-08-05T03:22:24.557 回答
0

在较新的 VB/C# .net 中,您感兴趣的关键字是 Await 和 Async: http: //msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx ?cs-save-lang=1&cs-lang= vb#code-snippet-1

此外,您应该设计您的例程以分块下载。有很多方法可以做到这一点,但也许你最好看看 HTTPWebRequest/Response 将处理分块并有一种方法可以轻松处理 +2GB 文件(范围)。

抱歉,没有答案,因为我没有足够的代表将其作为评论。

干杯,艾尔

于 2013-08-05T02:19:48.763 回答