Асинхронные параллельные веб-запросы в ASP. NET MVC (C#) - PullRequest
0 голосов
/ 17 апреля 2020

У меня есть мини-проект, требующий загрузки html документов с нескольких веб-сайтов с использованием C# и заставить его работать как можно быстрее. В моем сценарии мне может потребоваться переключить IP с помощью прокси на основе определенных условий. Я хочу воспользоваться C# Asynchronous Tasks, чтобы он выполнял как можно больше запросов, чтобы весь процесс был быстрым и эффективным.

Вот код, который у меня есть.

public class HTMLDownloader
{

    public static List<string> URL_LIST = new List<string>();
    public static List<string> HTML_DOCUMENTS = new List<string>();

    public static void Main()
    {
        for (var i = 0; i < URL_LIST.Count; i++)
        {
            var html = Task.Run(() => Run(URL_LIST[i]));
            HTML_DOCUMENTS.Add(html.Result);
        }
    }

    public static async Task<string> Run(string url)
    {
        var client = new WebClient();
        //Handle Proxy Credentials client.Proxy= new WebProxy();
        string html = "";
        try
        {
            html = await client.DownloadStringTaskAsync(new Uri(url));
            //if(condition ==true)
            //{
            //  return html;
            //}
            //else
            //{
            //  Switch IP and try again
            //}
        }
        catch (Exception e)
        {

        }

        return html;
    }

Проблема здесь в том, что я не пользуюсь преимуществом отправки нескольких веб-запросов, потому что каждый запрос должен заканчиваться sh для начала следующего. Есть ли лучший подход к этому? Например, отправляйте 10 веб-запросов одновременно, а затем отправляйте новый запрос, когда один из этих запросов будет завершен.

Спасибо

Ответы [ 3 ]

3 голосов
/ 17 апреля 2020

Я хочу воспользоваться C# Асинхронными задачами, чтобы он выполнял как можно больше запросов, чтобы весь процесс был быстрым и эффективным.

Вы можете использовать Task.WhenAll для получения асинхронного параллелизма.

Например, отправляйте 10 веб-запросов одновременно, а затем отправляйте новый запрос после завершения одного из этих запросов.

Для throttle асинхронного параллелизма используйте SemaphoreSlim:

public static async Task Main()
{
  using var limit = new SemaphoreSlim(10); // 10 at a time
  var tasks = URL_LIST.Select(Process).ToList();
  var results = await Task.WhenAll(tasks);
  HTML_DOCUMENTS.AddRange(results);

  async Task<string> Process(string url)
  {
    await limit.WaitAsync();
    try { return await Run(url); }
    finally { limit.Release(); }
  }
}
2 голосов
/ 17 апреля 2020

Одним из способов является использование Task.WhenAll.

Создает задачу, которая будет завершена после завершения всех поставленных задач.

Исходная посылка: Select все задачи в List, await список из задача с Task.WhenAll, Select результаты

public static async Task Main()
{
   var tasks = URL_LIST.Select(Run); 
   await Task.WhenAll(tasks);
   var results = tasks.Select(x => x.Result);
}

Примечание: результат WhenAll будет а также сбор результатов

0 голосов
/ 17 апреля 2020

Сначала измените Main на asyn c.

Затем вы можете использовать LINQ Select для параллельного запуска Tasks.

public static async Task Main()
{
    var tasks = URL_LIST.Select(Run);

    string[] documents = await Task.WhenAll(tasks);

    HTML_DOCUMENTS.AddRange(documents);
}

Task.WhenAll развернет результаты Task в массив после завершения всех задач.

...