По существу: да на обоих;конечный автомат генерируется, но не попадает в кучу, если он фактически не работает асинхронно.В некоторых критически важных для производительности сценариях, где большая часть вызовов оказывается синхронной, ручная реализация кода для переключения между синхронизацией и асинхронностью может быть выгодна:
static Task OneAsync()
{
async Task Awaited(Task t)
{
await t;
Console.WriteLine("OneAsync: End");
}
Console.WriteLine("OneAsync: Start");
var task = TwoAsync();
if (task.Status != TaskStatus.RanToCompletion)
return Awaited(task);
Console.WriteLine("OneAsync: End");
return task; // could also have used Task.CompletedTask
}
Обратите внимание, что для этого требуется некоторое ручное дублирование - вособенности того, что происходит с результатом или после него (Console.WriteLine
).Есть способы уменьшить это, часто вовлекая даже больше местных функций.Также обратите внимание, что task.Status
необычайно дорог, и, когда он доступен (.NET Core или ValueTask<T>
): IsCompletedSuccessfully
предпочтительнее.