You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VB.NET下载管理器:如何让循环等待当前下载完成后再执行?

VB.NET批量下载:解决WebClient并发I/O报错问题

你遇到的核心问题是**WebClient.DownloadFileAsync是异步非阻塞方法**,循环里直接连续调用会导致WebClient同时执行多个下载操作,触发WebClient does not support concurrent I/O operations错误。要实现串行批量下载,需要利用WebClient的DownloadFileCompleted事件来触发下一个下载任务,而非用循环直接连续发起请求。

修改后的代码实现

Imports Microsoft.VisualBasic.ApplicationServices
Imports Microsoft.VisualBasic.FileIO
Imports System
Imports System.Environment
Imports System.IO
Imports System.IO.Directory
Imports System.Net
Imports System.Net.Http
Imports System.Threading

Public Class Form1

    Dim strLocation As String
    Dim strFile As String
    Dim intSeason As Integer
    Dim SAVE As String
    Dim Show As String

    Private WithEvents httpClient As WebClient
    ' 记录当前下载的链接索引
    Private currentDownloadIndex As Integer = 0

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ofdBrowse.InitialDirectory = GetFolderPath(SpecialFolder.MyDocuments)
        ofdBrowse.Title = "Open file containing links"
        ofdBrowse.Filter = "Text Files|*.txt|All Files|*.*"
        ofdBrowse.ShowDialog()

        strLocation = ofdBrowse.FileName
        txtLocation.Text = strLocation
        strFile = strLocation

        Dim fileRead As New StreamReader(strFile)
        Dim Url As String
        Do While fileRead.Peek <> -1
            Url = fileRead.ReadLine()

            If Mid(Url, 1, 1) = "[" Then
                intSeason = CInt(Mid(Url, 9, 1))
            End If

            If Mid(Url, 1, 4) = "http" Then
                lbUrl.Items.Add(Url)
            End If
        Loop
        fileRead.Close() ' 释放文件资源

        Show = InputBox("Enter the name of the show")
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        If lbUrl.Items.Count = 0 Then
            MessageBox.Show("No download links found!")
            Return
        End If

        ' 初始化下载索引
        currentDownloadIndex = 0
        httpClient = New WebClient

        ' 创建保存目录
        Dim saveDir = $"{SpecialDirectories.Desktop}\{Show}\Season {intSeason}"
        If Not Exists(saveDir) Then
            CreateDirectory(saveDir)
        End If

        ' 启动第一个下载任务
        StartNextDownload()
    End Sub

    ' 启动下一个下载的封装方法
    Private Sub StartNextDownload()
        If currentDownloadIndex >= lbUrl.Items.Count Then
            MessageBox.Show("All downloads completed!")
            Return
        End If

        Dim URL = lbUrl.Items(currentDownloadIndex).ToString()
        SAVE = $"{SpecialDirectories.Desktop}\{Show}\Season {intSeason}\{Show} S{intSeason} E{currentDownloadIndex}.mkv"
        lbUrl.SelectedIndex = currentDownloadIndex
        httpClient.DownloadFileAsync(New Uri(URL), SAVE)
    End Sub

    Private Sub httpClientDownloadProgress(sender As Object, e As DownloadProgressChangedEventArgs) Handles httpClient.DownloadProgressChanged
        prgDownload.Value = e.ProgressPercentage
    End Sub

    ' 下载完成事件:触发下一个下载任务
    Private Sub httpClient_DownloadFileCompleted(sender As Object, e As System.ComponentModel.AsyncCompletedEventArgs) Handles httpClient.DownloadFileCompleted
        ' 可选:处理下载失败场景
        If e.Error IsNot Nothing Then
            MessageBox.Show($"Download failed for item {currentDownloadIndex}: {e.Error.Message}")
        End If

        ' 索引递增,启动下一个下载
        currentDownloadIndex += 1
        StartNextDownload()
    End Sub
End Class

关键修改说明

  1. 新增currentDownloadIndex变量:跟踪当前正在下载的链接在ListBox中的位置,确保串行执行顺序。
  2. 拆分StartNextDownload方法:统一处理单个下载任务的启动逻辑,避免重复代码。
  3. 利用DownloadFileCompleted事件:每次下载完成(无论成功/失败)自动触发下一个下载,保证同一时间只有一个下载任务在运行。
  4. 资源优化:关闭StreamReader避免文件资源泄漏;增加空链接列表判断,提升用户体验。

可选优化方向

  • 增加链接有效性预校验,避免无效链接触发下载错误。
  • 添加下载暂停/取消功能,通过httpClient.CancelAsync()实现。
  • 处理文件重名场景,避免覆盖已存在的文件。

内容的提问来源于stack exchange,提问作者Wilko84

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 10:22:03