обрабатывать коллекцию URL-адресов параллельно и возвращать IEnumerable

У меня есть набор URL-адресов для соскабливания, и я хочу параллельно загружать ресурсы, возвращая коллекцию строго типизированных результатов.

Имея WebClient.DownloadString() и " MyTypedResult Process (строка s) "

How do I wrap it up to have a string[] urls => IEnumerable conversion?

string[] urls = {"url1","url2","url3"};
List ResultCollection = new List();
foreach (var u in urls)
{
    WebClient wc = new WebClient();
    var content = wc.DownloadString(u);
    MyTypedResult r = Process(content);
    ResultCollection.Add(r);
}

Я хочу, чтобы веб-запросы выполнялись параллельно, но мне нужна результирующая коллекция в List;

1
Не совсем понятно, что вы просите. Пожалуйста, покажите еще несколько кодов.
добавлено автор Daniel Hilgarth, источник

3 ответы

Вы можете использовать новую игрушку HttpClient из .NET 4.5, чтобы получить результат параллельно:

var httpClient = new HttpClient();

var tasks = urls.Select(url => httpClient.GetStringAsync(url)
                        .ContinueWith(task =>
                        {
                            string response = task.Result;
                            return ConvertToStrongType(response);
                        }));

 Task.WaitAll(tasks.ToArray());
 var results = tasks.Select(t => t.Result);
3
добавлено
@Alexander Taran: Да, конечно, используя GetStringAsync, выполните параллельную работу кода
добавлено автор Cuong Le, источник
@AlexanderTaran: конечно, вы видите в фикере один за другим, но код с сервера использует Tasks process url, он почти означает каждый поток для каждого запроса. Изображение: отправив первое reuquest, код не дождался ответа ответа на процесс, он продолжает посылать второй запрос, это параллель, как вы это понимаете, правильно?
добавлено автор Cuong Le, источник
@AlexanderTaran: Я боюсь, что я не понимаю, почему два запроса одновременно. Но вы можете проверить код, запустив его, поставьте Thread.Sleep (5000), чтобы увидеть, что происходит
добавлено автор Cuong Le, источник
@AlexanderTaran: посмотрите временную метку в Fiddler, второй запрос приходит после первого в 5 секунд?
добавлено автор Cuong Le, источник
@AlexanderTaran: Где вы помещаете Thread.Sleep?
добавлено автор Cuong Le, источник
@AlexanderTaran: вы правы, я изменил ответ, PLS снова проверить
добавлено автор Cuong Le, источник
вау, это выглядит претированным простым. Я дам ему выстрел и посмотрю, куда он меня доставит.
добавлено автор Alexander Taran, источник
Теперь, если есть возможность запускать эти загрузки параллельно?
добавлено автор Alexander Taran, источник
Ну, глядя на запросы в скрипаче, они, безусловно, происходят один за другим.
добавлено автор Alexander Taran, источник
если бы это было так, тогда было бы как минимум два ожидающих запроса одновременно, но следующий запрос начинается только тогда, когда предыдущий закончен.
добавлено автор Alexander Taran, источник
Да, да. И он ждет 5 секунд между запросами. Не выполнять их параллельно друг другу.
добавлено автор Alexander Taran, источник
Да, через 5 секунд после первого.
добавлено автор Alexander Taran, источник
перед возвратом ConvertToStrongType
добавлено автор Alexander Taran, источник
@CuongLe есть ли способ ограничить количество задач, выполняемых параллельно?
добавлено автор PyQL, источник

Это версия Rx с HttpClient :

var urls = new[] { "url1", "url2", "url3" };
var client = new HttpClient();
var results = from url in urls.ToObservable()
              from content in client.GetStringAsync(url).ToObservable()
              select Process(content);
var enumerable = results.ToEnumerable();
2
добавлено

Ниже приведен код, он использует Parallel.ForEach для параллельной загрузки содержимого из URL-адреса. Вам необходимо использовать ConcurrentList, чтобы гарантировать, что сбор должен быть заполнен параллельно, без проблемы блокировки потока.

void YourTask()
{
    string[] urls = {"url1","url2","url3"};
    ConcurrentList ResultCollection = new ConcurrentList();

    Parallel.ForEach(urls, url => 
    {
        GetData(url);
        ResultCollection.TryAdd(myTypedResult);
    );

    //on this line all parallel task will be completed and ResultCollection will be filled with the results

}

MyTypedResult GetData(string url)
{
   WebClient wc = new WebClient();
    var content = wc.DownloadString(url);
    MyTypedResult r = Process(content);
    return r;
}
1
добавлено
Microsoft Stack Jobs
Microsoft Stack Jobs
1 788 участник(ов)

Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks

Microsoft Developer Community Chat
Microsoft Developer Community Chat
584 участник(ов)

Чат для разработчиков и системных администраторов Microsoft Developer Community. __________ Новостной канал: @msdevru __________ Баним за: оскорбления, мат, рекламу, флуд, флейм, спам, NSFW контент, а также большое количество оффтоп тем. @banofbot