WebClient.DownloadFile () в Parallel.ForEach - PullRequest
4 голосов
/ 29 марта 2011

Этот код работает нормально:

Parallel.ForEach(photos, item =>
            {
                WebClient webClient = new WebClient();
                webClient.DownloadFile(item.src_big, "C:\\pic" + item.ID + ".jpg");
            });

Пока этот код выдает «Возникла исключительная ситуация во время запроса WebClient».:

foreach (Photo p in photos)
        {
            Task.Factory.StartNew(() =>
                {
                    WebClient webClient = new WebClient();
                    webClient.DownloadFile(p.src_big, "C:\\pic" + p.ID + ".jpg");
                });
        }

У меня два вопроса:

1) В первом коде я использую несколько объектов WebClient для загрузки.То же самое относится и ко второму коду, так почему я получаю исключение?

2) Я пробую эти две версии, чтобы определить, какой самый быстрый способ загрузки фотографий, в моем случае с Facebook.Я хотел бы знать, если есть другой метод, который быстрее, может быть, WebRequest.Create ()?

Ответы [ 2 ]

7 голосов
/ 29 марта 2011

Вы закрываете переменную цикла во втором случае - попробуйте это:

foreach (Photo p in photos)
        {
            Photo photo = p;
            Task.Factory.StartNew(() =>
                {
                    WebClient webClient = new WebClient();
                    webClient.DownloadFile(photo.src_big, "C:\\pic" + photo.ID + ".jpg");
                });
        }

Также Parallel.ForEach() является синхронным - после выполнения все файлы были загружены. Задачи, с другой стороны, все еще могут выполняться, поэтому вам придется ждать, пока они завершатся, возможно, что-то подобное будет более подходящим для второго случая:

var tasks = photos.Select(  p => Task.Factory.StartNew(() =>
        {
            using(WebClient webClient = new WebClient())
            webClient.DownloadFile(p.src_big, string.Format(@"C:\pic{0}.jpg",p.ID));
        })).ToArray();
Task.WaitAll(tasks);

Как видите, Parallel.ForEach() в этом случае гораздо предпочтительнее, поскольку синтаксис очень лаконичен, под капотом они оба используют Пул потоков, поэтому выберите самый простой вариант, с которым вы можете обойтись, особенно если вы этого не делаете. нужна дополнительная сложность.

Также я не думаю, что вы будете получать свои данные быстрее, используя WebRequest - большая часть задержки будет вызвана сетью / интернетом, а не тем, какой из двух вы выберете - в таком случае я бы выберите более простой код, который определенно использует WebClient.

Подводя итог: я бы пошел на Parallel.ForEach() с WebClient, опция 1 .

0 голосов
/ 29 марта 2011

Отвечая на вопрос 2, я использую ту же процедуру, и она работает для меня параллельно. Forex значительно сократил время

Когда я проанализировал статику, то заметил, что если у меня есть большое количество изображений для извлечения, то параллельно. Foreach запускает так много потоков, что почти достигает пропускной способности моей широкополосной сети, как если бы у меня была максимальная обычная скорость загрузки 100 КБ / с. таким образом, загрузка фотографий достигла 100 КБ, это означает, что она не может быть лучше, чем эта, потому что именно Интернет имеет наибольшее значение

...