Как отправить несколько веб-запросов и обработать их максимально быстро - PullRequest
0 голосов
/ 11 апреля 2019

Я работаю над приложением winforms на C # и у меня есть около 84 URL-адресов, которые я хочу проанализировать с помощью html agility pack

для 84 записей требуется 150 секунд для выполнения задания с кодом ниже.

Мне было интересно, какие варианты у меня есть, чтобы он работал быстрее? любая помощь очень ценится!

Ниже приведена моя структура кода для выполнения работы

public class URL_DATA
{
    public string URL { get; set; }
    public HtmlDocument doc  { get; set; }
}

then I call the below function to do the job

 public async Task ProcessUrls(string cookie)
 {
                var tsk = new List<Task>();
                //UrlsToProcess is List<URL_DATA>
                UrlsToProcess.ForEach(async data =>
                {
                    tsk.Add(Task.Run(async () => 
                    {
                      var htmToParse =  await ScrapUtils.GetAgilityDocby(cookie, data.URL);

                        var htmlDoc = new HtmlDocument();
                        htmlDoc.LoadHtml(htmToParse);
                        data.doc = htmlDoc;

                    }));

                });
                await Task.WhenAll(tsk).ConfigureAwait(false);    
   }

и, наконец, ниже - метод, который я использую для получения строки запроса.

 public static async Task<string> GetAgilityDocby(string cookie, string url)
        {
            using (var wc = new WebClient())
            {
                wc.Proxy = null;// WebRequest.DefaultWebProxy;// GlobalProxySelection.GetEmptyWebProxy();
                wc.Headers.Add(HttpRequestHeader.Cookie, cookie);

                wc.Headers.Add(HttpRequestHeader.UserAgent,
                    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36");
                wc.Encoding = Encoding.UTF8;
                test++;
                return await  wc.DownloadStringTaskAsync(url).ConfigureAwait(false);
            }
        }

Ответы [ 2 ]

0 голосов
/ 11 апреля 2019

Вы используете ForEach с асинхронной лямбдой. У меня есть подозрение, что это заставляет ваш код работать последовательно, а не параллельно, поскольку каждая следующая итерация будет ждать.

Итак, что вы можете сделать, чтобы понять это наверняка:

  1. Проверьте максимальное время операции для одного URL, это время должно быть примерно таким, как быстро все должно идти (если у вас достаточно пропускной способности, памяти и процессора).
  2. Убедитесь, что ваши операции действительно выполняются параллельно. Например. путем вывода счетчика на консоль. Он не должен быть последовательным и выглядеть достаточно случайным

Вы можете изменить код создания задачи на этот, например. попробовать:

var allTasks = myUrls.Select(url => Task.Run(() => {yourCode})
Task.WhenAll(allTasks);
0 голосов
/ 11 апреля 2019

Попробуйте увеличить минимальный рабочий номер потока на

ThreadPool.SetMinThreads(84,84);

Это должно значительно ускорить процесс.

Что касается создания задач, на которое указал Илья, я бы порекомендовал вам опуститьTask.Run / AwaitВсе полностью и использовать механизм Parallel, который был разработан именно для такой проблемы:

Parallel.ForEach(UrlsToProcess, data =>
{
    var htmToParse =  ScrapUtils.GetAgilityDocby(cookie, data.URL);

    var htmlDoc = new HtmlDocument();
    htmlDoc.LoadHtml(htmToParse);
    data.doc = htmlDoc;
});
...