Может кто-нибудь, дайте мне знать, когда мы используем одно вместо другого с двумя нижеприведенными реализациями:
await Task.Run(async () => Method());
await Task.Run(() => Method());
Какова цель использования async в вызове Task.Run()?
Если у вас случай 1, то @John верен, за исключением того, что его можно упростить до await Method()
Предполагая, что Method возвращает задачу, 1 / не имеет преимущества перед 2 / и имеет небольшие накладные расходы из-за распределения конечного автомата.
@NathanWerry Не обязательно. Если метод блокирует поток на значительный период времени, прежде чем уступить, может быть законным запустить его в отдельном потоке (например, чтобы избежать блокировки пользовательского интерфейса).
@KevinGosse, я расширял то, что прокомментировал Джон, в котором у него есть функция, которая является асинхронной, так что да, это предположение было, но, вероятно, должно было быть упомянуто. Кроме того, он выполняется в отдельном потоке. Функция уже использует шаблон async / await, поэтому мы можем просто написать await вместо того, чтобы заключать асинхронную задачу в асинхронную задачу.





Если вызываемый вами метод является асинхронным, вы можете использовать async / await в функции.
async Task MainAsync()
{
await Task.Run(async () => await MethodAsync());
await Task.Run(() => Method());
}
async Task MethodAsync() { ... }
void Method() { ... }
В чем преимущество await Task.Run(async () => await MethodAsync()); перед await MethodAsync();?
Как упоминалось в комментарии к вопросу, строка 3 является чрезмерным усложнением и может быть сокращена до await MethodAsync().
Нет реальной причины использовать №1. Смысл использования Task.Run заключается в том, чтобы сделать длительную задачу или единицу работы с интенсивным вводом-выводом и сделать ее асинхронной, а поскольку №1 уже является асинхронным, асинхронная анонимная функция внутри Task.Run является избыточной и ненужной.
Либо вы выполните следующие действия, чтобы преобразовать единицу работы в асинхронную:
await Task.Run(() => Method());
public void Method()
{
//doing intensive work here
}
Или вы просто await - уже асинхронную единицу работы.
await MethodAsync();
public async Task MethodAsync()
{
//doing async work here
}
Task.Run заключается в том, чтобы обернуть единицу работы, интенсивно потребляющую ЦП, так как она будет заключать ее в задачу, основанную на потоках. Ввод-вывод обычно можно сделать асинхронным без необходимости в потоках (вместо использования событий), что, в свою очередь, означает, что единицу работы с интенсивным вводом-выводом не следует заключать в Task.Run, потому что вы потратите поток впустую. чтобы получить. Но в целом вы правы, что перенос задачи в Task.Run избыточен. Единственный сценарий, в котором имеет смысл обернуть задачу в Task.Run, - это если задача связана с вводом-выводом, но также выполняет тяжелые вычисления, поскольку для них не будет потока, который был бы асинхронным.
Вы уверены, что? В документации по async есть несколько упоминаний о чтении и записи файлов. docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…
Да, чтение / запись файлов - это задача, связанная с вводом-выводом, которую не нужно заключать в Task.Run, о чем и была моя первая часть. Моя вторая часть была о некоторой гипотетической функции EncryptAsync(string fileName), которая возвращает задачу, поскольку использует асинхронные файловые функции. Однако в этом случае шифрование может быть дорогостоящим с вычислительной точки зрения, но все равно будет выполняться в вызывающем основном (UI) потоке, потому что функции асинхронного ввода-вывода часто не используют потоки для асинхронности. В этом случае имеет смысл заключить EncryptAsync в Task.Run, чтобы часть шифрования выполнялась в отдельном потоке.
Должен ли я быть
await Task.Run(async () => await Method());?