Разница между вызовом асинхронного метода и переносом вызова в Task.Run

Я пытаюсь написать асинхронное задание, которое работает в фоновом режиме. Есть два способа сделать это -

[Test]
public async Task method1()
{ 
    Task task = run();
    await Task.WhenAll(task);
}

[Test]
public async Task method2()
{
    Task task = Task.Run(async() =>
    {
        await run();
    });
    await Task.WhenAll(task);
}

public async Task run()
{
    Console.WriteLine("Current Thread Name: " + Thread.CurrentThread.Name);
    // background thread to print numbers with sleep of 1s
    await Task.Run(() =>
    {
        for (int i = 1; i <= 2; i++)
        {
            Console.Write(i + " ");
            Thread.Sleep(1000);
        }
        Console.WriteLine();
    });
}

method1 принты

Current Thread Name: NonParallelWorker
1 2

где как печатает method2

Current Thread Name: .NET TP Worker
1 2

Мне было интересно, в чем разница между этими двумя подходами и как это повлияет на мое приложение. Функционально оба выполняют одно и то же — асинхронное выполнение задания в фоновом режиме.

​Кроме того, method1, method2 и run не являются собственными именами методов в C#. Имена методов в C# имеют регистр PascalCased. Method1, Method2 и Run верно. См.: Правила и соглашения об именовании идентификаторов C#.

Theodor Zoulias 02.07.2024 23:32

По теме: await Task.Run vs await.

Theodor Zoulias 02.07.2024 23:36
Task.Run создает тему. await нет. Вам следует использовать await Task.Delay, а не Thread.Sleep. Начните читать Нитки нет.
Dour High Arch 02.07.2024 23:41
Task.Run в основном не создает новую тему. io-потоки тоже являются потоками.
Ivan Petrov 03.07.2024 00:23
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
4
72
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Метод Task.Run вызывает действие в ThreadPool и возвращает Task, обозначающий завершение этого действия. Если действие асинхронное, как в вашем случае, Task.Run по-прежнему вызывает действие в ThreadPool и возвращает прокси Task, который представляет как создание внутренней задачи, так и последующее завершение этой задачи. Если вас интересуют подробности, вы можете прочитать эту статью Microsoft.

Если вы хотите выгрузить часть синхронного кода в ThreadPool, достаточно обернуть его один раз в Task.Run. Обертывание его дважды или более не добавляет ничего, кроме трения:

// Exercise to futility
Task task = Task.Run(async () =>
{
    await Task.Run(async () =>
    {
        await Task.Run(async () =>
        {
            await Task.Run(async () =>
            {
                await Task.Run(async () =>
                {
                    await run();
                });
            });
        });
    });
});

Мне было интересно, в чем разница между этими двумя подходами и как это повлияет на мое приложение.

Обертывание двух Task.Run одного внутри другого не будет иметь заметного значения. Влияние на производительность вряд ли будет заметным. .NET ThreadPool — очень эффективное программное обеспечение, которое легко справляется с подобными злоупотреблениями.

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

Создать каталог, только если он не существует (.NET)
Foreach нельзя использовать для переменных типа «PropertyInfo», поскольку «PropertyInfo» не имеет определения для «GetEnumerator»
Положение большого пальца динамической сетки данных WPF изменилось, когда определение строки и столбца добавляется в выбранную динамическую сетку
Указание симулятора IOS при запуске приложения с помощью инструментов командной строки .NET
Код ошибки MSB4062 в проекте функции Azure в VS для запуска API Microsoft Graph с функциями Azure
Отключить закрытие начальной загрузки вне холста при щелчке по фону в приложении Blazor .NET
Целые числа, допускающие значение NULL – почему не возникает исключение?
Можем ли мы предоставить участнику данных BLOB-объектов хранилища разрешение на регистрацию приложения Azure?
Как запустить EF Core ExecuteUpdateAsync и добавить новый объект как часть этого обновления?
С этим соединением уже связан открытый DataReader, который необходимо закрыть при первой ошибке

Похожие вопросы

Как мне отформатировать строковое значение из пользовательского списка в денежный формат?
Создать каталог, только если он не существует (.NET)
Почему INumber<T>.CreateX(int n) настолько медленный по сравнению с неявным преобразованием для чисел с плавающей запятой и двойной точности?
VS 2022 Добавить ссылку на службу, не генерирующую ClientCredentials для .Net Framework
Как определить конкретный шаблон для конфигурации пути пряжи
Foreach нельзя использовать для переменных типа «PropertyInfo», поскольку «PropertyInfo» не имеет определения для «GetEnumerator»
Некоторые свойства отсутствуют в DirectX 11 по сравнению с 9-й версией
Как отделить SQL от кода при использовании параметризованных запросов?
Использование Effort с расширениями EF. WhereBulkContains выдает System.Exception
Как предотвратить вызов загруженных выгруженных методов Pages и UC, когда пользователь повторно подключает RDC в WPF C#?