Первый подход предусматривает просто использование свойства Result
Task, или метода Wait() с методами, возвращающими Task/Task. (Вспомните, что метод, который возвращает значение, обязан возвращать Task, будучи асинхронным, а метод, не имеющий возвращаемого значения, возвращает Task, когда является асинхронным.) Если метод терпит неудачу, то возвращается AggregateException.Можете также добавить вызов GetAwaiter().GetResult()
await в асинхронном методе, и распространяет исключения в той же манере, что и async/await. Тем не менее, указанные методы помечены в документации как "не предназначенные для внешнего использования", а это значит, что они могут измениться либо вовсе исчезнуть в какой-то момент в будущем. Вызов GetAwaiter().GetResult() работает как с методами, возвращающими значение, так и с методами без возвращаемого значения.На заметку!
Решение использовать свойствоResult или вызов GetAwaiter().GetResult() с Task возлагается полностью на вас, и большинство разработчиков принимают решение, основываясь на обработке исключений. Если ваш метод возвращает Task, тогда вы должны применять вызов GetAwaiter().GetResult() или Wait().Например, вот как вы могли бы вызывать метод DoWorkAsync()
Console.WriteLine(DoWorkAsync().Result
Console.WriteLine(DoWorkAsync().GetAwaiter().GetResult()
Чтобы остановить выполнение до тех пор, пока не произойдет возврат из метода с возвращаемым типом void
Wait() на объекте Task:MethodReturningVoidAsync().Wait();
Ожидание с помощью await в блоках catch и finally
В версии C# 6 появилась возможность помещения вызовов await в блоки catch
finally. Для этого сам метод обязан быть async. Указанная возможность демонстрируется в следующем примере кода:static async Task
{
try
{
//Do some work
return "Hello";
}
catch (Exception ex)
{
await LogTheErrors();
throw;
}
finally
{
await DoMagicCleanUp();
}
}
Обобщенные возвращаемые типы в асинхронных методах (нововведение в версии 7.0)
До выхода версии C# 7 возвращаемыми типами методов async
Task, Task и void. В версии C# 7 доступны дополнительные возвращаемые типы при условии, что они следуют шаблону с ключевым словом async. В качестве конкретного примера можно назвать тип ValueTask. Введите код, подобный показанному ниже:static async ValueTask
{
await Task.Delay(1_000);
return 5;
}
К типу ValueTask
Task, поскольку ValueTask — это просто объект Task для типов значений, заменяющий собой принудительное размещение объекта в куче.Локальные функции (нововведение в версии 7.0)
Локальные функции были представлены в главе 4 и использовались в главе 8 с итераторами. Они также могут оказаться полезными для асинхронных методов. Чтобы продемонстрировать преимущество, сначала нужно взглянуть на проблему. Добавьте новый метод по имени MethodWithProblems()
static async Task MethodWithProblems(int firstParam, int secondParam)
{
Console.WriteLine("Enter");
await Task.Run(() =>
{
// Вызвать длительно выполняющийся метод
Thread.Sleep(4_000);
Console.WriteLine("First Complete");
// Вызвать еще один длительно выполняющийся метод, который терпит
// неудачу из-за того, что значение второго параметра выходит
// за пределы допустимого диапазона.
Console.WriteLine("Something bad happened");
});
}