Истинные параллельные загрузки - PullRequest
1 голос
/ 16 июля 2011

Этот метод я использую для одновременных загрузок.

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, формирует очередь.

Ответы [ 2 ]

13 голосов
/ 16 июля 2011

Члены экземпляра WebClient не являются поточно-ориентированными, поэтому убедитесь, что у вас есть отдельные экземпляры в каждом действии. В методе, который вы показали, вы, кажется, умножаете один и тот же делегат действия несколько раз. Таким образом, вы не загружаете разные URL, вы загружаете один и тот же URL несколько раз. А поскольку WebClient не является потокобезопасным, вы можете столкнуться с проблемами.

Вот пример параллельной загрузки нескольких URL-адресов с использованием TPL:

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);
    }
}
5 голосов
/ 21 июля 2015

Чтобы улучшить ответ @ Darin-Dimitrov, вы можете извлечь result из client.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;            
        }
...