【问题标题】:True Parallel Downloads真正的并行下载
【发布时间】:2011-07-16 08:35:07
【问题描述】:

我正在使用此方法进行并发下载。

public void DownloadConcurrent(Action Method)
        {
            Action[] methodList = new Action[Concurent_Downloads];

            for (int i = 0; i < Concurent_Downloads; i++)
            {
                methodList[i] = Method;
            }

            Parallel.Invoke(methodList);
        }

我正在尝试同时下载 url,但活动下载次数始终为 1。

好像所有的下载都会调用,但只有一个 url 会开始下载数据,而不是所有的都会开始下载。

我希望所有下载同时进行,但无法实现。

更新:该方法使用队列,它正在下载不同的 url,形成队列。

【问题讨论】:

  • Action 委托中的代码是什么样的?

标签: c# .net windows download webclient


【解决方案1】:

WebClient 的实例成员不是线程安全的,因此请确保在每个操作中都有单独的实例。在您展示的方法中,您似乎多次乘以相同的动作委托。因此,您不是在下载不同的 url,而是在多次下载相同的 url。而且由于 WebClient 不是线程安全的,您可能会遇到问题。

以下是使用 TPL 并行下载多个 url 的示例:

using System;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        var urls = new[] 
        { 
            "http://google.com", 
            "http://yahoo.com", 
            "http://stackoverflow.com" 
        };

        var tasks = urls
            .Select(url => Task.Factory.StartNew(
                state => 
                {
                    using (var client = new WebClient())
                    {
                        var u = (string)state;
                        Console.WriteLine("starting to download {0}", u);
                        string result = client.DownloadString(u);
                        Console.WriteLine("finished downloading {0}", u);
                    }
                }, url)
            )
            .ToArray();

        Task.WaitAll(tasks);
    }
}

【讨论】:

    【解决方案2】:

    要改进@Darin-Dimitrov 的答案,您可以使用此改进功能从client.DownloadString() 中检索result 以在其他地方使用:

    
    public List<string> DownloadUrlsInParallel(Uri[] urls)
            {            
                var tasks = urls
                    .Select(url => Task.Factory.StartNew(
                        state =>
                        {
                            using (var client = new System.Net.WebClient())
                            {
                                var u = (Uri)state;
                                Console.WriteLine("starting to download {0}", u);
                                string result = client.DownloadString(u);
                                Console.WriteLine("finished downloading {0}", u);
                                return result;
                            }
                        }, url)
                    )
                    .ToArray();
    
                Task.WaitAll(tasks);
                List<string> ret = new List();
                foreach(var t in tasks)
                {
                    ret.Add(t.Result);
                }
                return ret;            
            }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多