【问题标题】:DownloadStringAsync multiple URLs maintaining orderDownloadStringAsync 多个 URL 维护顺序
【发布时间】:2013-10-20 17:35:23
【问题描述】:

我需要下载多个 HTML 页面作为字符串并将它们存储到一个列表中。但随后需要按我开始下载的顺序存储。目前该列表按下载完成的顺序排列。因此,当下载完成时,其内容会被添加到列表中。但它们不一定按照开始的顺序完成。我对如何按照它们开始的顺序将这些数据存储在列表中感到有些困惑。

这是我当前的代码,它会启动下载序列。 URLList 是一个 url 列表,我需要下载的字符串与这个原始列表的顺序相同:

cts = new CancellationTokenSource();
try
{
    await AccessTheWebAsync(cts.Token);
    listBox1.DataSource = VideoList;
}
catch (Exception)
{
    MessageBox.Show("\r\nDownload failed.\r\n");
}
cts = null;

然后调用如下代码:

async Task AccessTheWebAsync(CancellationToken ct)
{
    HttpClient client = new HttpClient();
    client.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");

    IEnumerable<Task<string>> downloadTasksQuery = from url in URLList select ProcessURL(url, client, ct);

    List<Task<string>> downloadTasks = downloadTasksQuery.ToList();

    while (downloadTasks.Count > 0)
    {
        Task<string> firstFinishedTask = await Task.WhenAny(downloadTasks);

        downloadTasks.Remove(firstFinishedTask);

        string length = await firstFinishedTask;  //this is the data of the first finished download
        int refPoint = length.IndexOf("Download (Save as...): <a href=\"") + 32;
        VideoList.Add(length.Substring(refPoint, length.IndexOf("\">", refPoint) - refPoint));
    }
}

async Task<string> ProcessURL(string url, HttpClient client, CancellationToken ct)
{
    HttpResponseMessage response = await client.GetAsync(url, ct);
    string urlContents = await response.Content.ReadAsStringAsync();
    return urlContents;
}

我确定它相当简单。但我只需要下载的字符串与原始 URLList 列表的顺序相同。任何帮助将不胜感激。

【问题讨论】:

    标签: c# html url asynchronous


    【解决方案1】:

    未经测试,但这应该可以工作。

    async Task AccessTheWebAsync(CancellationToken ct)
    {
        HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
    
        var downloadTasks = new List<Task<Tuple<string, int>>();
    
        int index = 0;
        foreach(var url in URLList)
            downloadTasks.Add(ProcessURL(url, client, ct, index++));
    
        while (downloadTasks.Count > 0)
        {
            Task<Tuple<string, int>> firstFinishedTask = await Task.WhenAny(downloadTasks);
    
            downloadTasks.Remove(firstFinishedTask);
    
            Tuple<string, int> result = await firstFinishedTask;  //this is the data of the first finished download
            int refPoint = result.Item1.IndexOf("Download (Save as...): <a href=\"") + 32;
            VideoList.Add(length.Item1.Substring(refPoint, length.IndexOf("\">", refPoint) - refPoint));
        }
    }
    
    async Task<Tuple<string, int>> ProcessURL(string url, HttpClient client, CancellationToken ct, int index)
    {
        HttpResponseMessage response = await client.GetAsync(url, ct);
        string urlContents = await response.Content.ReadAsStringAsync();
        return Tuple.Create(urlContent, index);
    }
    

    【讨论】:

    • 我已经尝试了您的代码,但出现了一些错误,我修复了 1 但不确定如何修复另一个。我对 C# 还是有点陌生​​。它在“字符串长度 = await firstFinishedTask;”这一行上
    • 我已经更新了代码。 result.Item2 包含下载任务的索引。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-27
    • 2015-09-12
    • 2011-10-25
    • 2012-04-12
    • 1970-01-01
    相关资源
    最近更新 更多