Я в процессе обновления библиотеки, которая имеет поверхность API, которая была построена в .NET 3.5. В результате все методы синхронны. Я не могу изменить API (т.е. Преобразовать возвращаемые значения в Task), потому что это потребует изменения всех вызывающих абонентов. Поэтому я остался с тем, как наилучшим образом использовать методы async синхронно. Это в контексте приложений ASP.NET 4, ASP.NET Core и .NET/.NET Core.
Возможно, я не был достаточно ясен - ситуация в том, что у меня есть существующий код, который не является асинхронным, и я хочу использовать новые библиотеки, такие как System.Net.Http и AWS SDK, которые поддерживают только асинхронные методы. Поэтому мне нужно устранить пробел и иметь код, который можно вызвать синхронно, но затем может вызывать методы async в другом месте.
Я много читал, и есть несколько раз, на что это было задано и ответили.
Вызов метода асинхронизации из неасинхронного метода
Синхронное ожидание операции async и почему Wait() заморозит программу здесь
Вызов метода асинхронного синхронного метода
Как выполнить задачу async <T> метод синхронно?
Синхронно вызов метода асинхронного подключения
Как вызвать асинхронный метод из синхронного метода в С#?
Проблема в том, что большинство ответов разные! Наиболее распространенный подход, который я видел, это использовать. Результат, но это может быть взаимоблокировка. Я пробовал все следующее, и они работают, но я не уверен, что это лучший подход, чтобы избежать взаимоблокировок, иметь хорошую производительность и хорошо играть со временем выполнения (с точки зрения соблюдения планировщиков задач, вариантов создания задач и т.д.). Есть ли окончательный ответ? Каков наилучший подход?
private static T taskSyncRunner<T>(Func<Task<T>> task)
{
T result;
// approach 1
result = Task.Run(async () => await task()).ConfigureAwait(false).GetAwaiter().GetResult();
// approach 2
result = Task.Run(task).ConfigureAwait(false).GetAwaiter().GetResult();
// approach 3
result = task().ConfigureAwait(false).GetAwaiter().GetResult();
// approach 4
result = Task.Run(task).Result;
// approach 5
result = Task.Run(task).GetAwaiter().GetResult();
// approach 6
var t = task();
t.RunSynchronously();
result = t.Result;
// approach 7
var t1 = task();
Task.WaitAll(t1);
result = t1.Result;
// approach 8?
return result;
}