Task.Run для метода, возвращающего T VS метод, возвращающий Task<T>

Сценарий 1. Для каждого веб-сайта в списке строк (_websites) метод вызывающей стороны оборачивает GetWebContent в задачу, ожидает завершения всех задач и возвращает результаты.

    private async Task<string[]> AsyncGetUrlStringFromWebsites()
    {
        List<Task<string>> tasks = new List<Task<string>>();

        foreach (var website in _websites)
        {
            tasks.Add(Task.Run(() => GetWebsiteContent(website)));
        }

        var results = await Task.WhenAll(tasks);

        return results;
    }

    private string GetWebContent(string url)
    {
        var client = new HttpClient();

        var content = client.GetStringAsync(url);

        return content.Result;
    }

Сценарий 2. Для каждого веб-сайта в списке строк (_websites) вызывающий метод вызывает GetWebContent (возвращает Task), ожидает завершения всех задач и возвращает результаты.

    private async Task<string[]> AsyncGetUrlStringFromWebsites()
    {
        List<Task<string>> tasks = new List<Task<string>>();

        foreach (var website in _websites)
        {
            tasks.Add(GetWebContent(website));
        }

        var results = await Task.WhenAll(tasks);

        return results;
    }

    private async Task<string> GetWebContent(string url)
    {
        var client = new HttpClient();

        var content = await client.GetStringAsync(url);

        return content;
    }

Вопросы - Как правильно и почему? Как каждый подход влияет на достижение асинхронной обработки?

2 ответа

Решение

С Task.Run() вы занимаетесь потоком из пула потоков и говорите ему подождать, пока веб-контент не будет получен.
Почему вы хотите это сделать? Платите ли вы кому-нибудь, чтобы он стоял рядом с вашим почтовым ящиком и сообщал вам, когда приходит письмо?

GetStringAsync уже асинхронный. Процессор не имеет ничего общего (с этим процессом), пока контент поступает по сети.

Таким образом, второй подход верен, здесь нет необходимости использовать дополнительные потоки из пула потоков.

Всегда интересно читать: Стивена Клири "Нет ветки"

@ Рене Фогт дал отличное объяснение.

Там незначительные 5 центов с моей стороны.

Во втором примере нет необходимости использовать async / await в GetWebContent метод. Вы можете просто вернуться Task<string> (это также уменьшит async глубина).

Другие вопросы по тегам