Как оптимизировать несколько веб-запросов в C#? - PullRequest
0 голосов
/ 20 января 2020

Мне нужно проверить около 10 URL (иногда больше) в приложении WPF и отобразить результат (просто «подключен» или «не удается подключиться».

Я сделал что-то, что работает, с кодом ниже:

foreach (string url in urlList)
{
    CheckConnection(url); 
}

static async void CheckConnection(string url)
{
    using (WebClient client = new WebClient())
    {
        bool succeed = true;
        try
        {
            await Task.Run(() => client.DownloadData(url));
        }
        catch
        {
            succeed = false;
        }

        if (succeed){ 
            //display "is connected"
        }
        else{
            //display "can't connect"
        }
    }
}

Проблема в том, что проверка всего занимает слишком много времени, я не знаю почему, кажется, что это занимает гораздо больше времени, чем следовало. Как я могу оптимизировать это ? Что я делаю лучший способ сделать это?

Ответы [ 2 ]

2 голосов
/ 20 января 2020

Вы можете использовать Task.WhenAll для массива задач: https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.whenall?view=netframework-4.8

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

Вот пример того, что я имею в виду:


var tasks = new List<Task>();
using (WebClient client = new WebClient())
{
    foreach (string url in urlList)
    {
        tasks.Add(client.DownloadData(url)));
    }

    await Task.WhenAll(tasks);
}

Это, по сути, запустит все запросов, затем ждет их выполнения, прежде чем продолжить, значит что вы делаете не один запрос, ожидание, второй запрос, ожидание и т. д. c ....

Несколько замечаний по поводу вашего кода:

Вам следует не возвращать void при выполнении асинхронного кода

Вот некоторая информация: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/async-return-types#BKMK_VoidReturnType

Вы используете тип возврата void в обработчиках асинхронных событий, которые требуется тип возврата void. Для методов, отличных от обработчиков событий, которые не возвращают значение, вы должны вместо этого вернуть Task, потому что нельзя ожидать asyn c метода, который возвращает void. Любой вызывающий такой метод должен иметь возможность продолжить выполнение, не дожидаясь, пока вызываемый метод asyn c завершится до sh, и вызывающий должен быть независим от любых значений или исключений, которые генерирует метод asyn c.

HttpClient - это новый API

WebClient Я думаю, это старый способ ведения дел? C# быстро движется в эти дни: { ссылка } у него аналогичная производительность, и вы можете использовать его очень похожим образом

Вы, вероятно, должны проверять код состояния, а не перехватывать исключения

Я мог бы написать эссе о разрешении исключений для создания потока управления, но пока давайте будем простыми, коды состояния http могут определять, успешны они или нет - используйте их.

Надеюсь, это поможет

1 голос
/ 20 января 2020

Вы должны использовать API HttpClient и вызывать запросы асинхронно:

static async Task<bool> CheckConnection(List<string> urlList)
{
    bool succeed = true;
    using (HttpClient client = new HttpClient())
    {
        var tasks = urlList.Select(x => client.GetByteArrayAsync(x)).ToArray();
        try
        {
            await Task.WhenAll(tasks);
        }
        catch
        {
            succeed = false;
        }
    }
    return succeed;
}

Вам не нужен поток для выполнения веб-запроса. Это пустая трата ресурсов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...