Я пытаюсь написать асинхронное задание, которое работает в фоновом режиме. Есть два способа сделать это -
[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
Мне было интересно, в чем разница между этими двумя подходами и как это повлияет на мое приложение. Функционально оба выполняют одно и то же — асинхронное выполнение задания в фоновом режиме.
По теме: await Task.Run vs await.
Task.Run
создает тему. await
нет. Вам следует использовать await Task.Delay
, а не Thread.Sleep
. Начните читать Нитки нет.
Task.Run
в основном не создает новую тему. io-потоки тоже являются потоками.
Метод 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
— очень эффективное программное обеспечение, которое легко справляется с подобными злоупотреблениями.
Кроме того,
method1
,method2
иrun
не являются собственными именами методов в C#. Имена методов в C# имеют регистр PascalCased.Method1
,Method2
иRun
верно. См.: Правила и соглашения об именовании идентификаторов C#.