真正的并行下载

Mil*_*nki 1 .net c# windows webclient download

这个方法我用于并发下载.

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);
        }
Run Code Online (Sandbox Code Playgroud)

我正在尝试同时下载网址,但有效下载的数量始终为1.

就像所有下载都会调用一样,但只有一个url会开始下载数据,而不是所有下载都会开始下载.

我希望所有下载同时并行工作,无法实现.

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

Dar*_*rov 13

WebClient的实例成员不是线程安全的,因此请确保每个操作中都有单独的实例.在您显示的方法中,您似乎多次将相同的操作委托相乘.所以你没有下载不同的网址,你多次下载相同的网址.并且因为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);
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

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


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;            
        }
Run Code Online (Sandbox Code Playgroud)