我正在更新具有.NET 3.5中内置的API表面的库。结果,所有方法都是同步的。我无法更改API(即,将返回值转换为Task),因为这将要求所有调用者都进行更改。因此,我剩下如何以同步方式最好地调用异步方法了。这是在ASP.NET 4,ASP.NET Core和.NET / .NET Core控制台应用程序的上下文中。
我可能还不够清楚-这种情况是我有不支持异步的现有代码,并且我想使用仅支持异步方法的新库,例如System.Net.Http和AWS开发工具包。因此,我需要弥合差距,并能够拥有可以被同步调用但可以在其他地方调用异步方法的代码。
我已经读了很多书,而且有很多次被问及回答了。
问题是大多数答案都不一样!我见过的最常见的方法是使用.Result,但这会导致死锁。我已经尝试了以下所有方法,并且它们都能正常工作,但是我不确定哪种方法可以避免死锁,具有良好的性能并且可以在运行时很好地发挥作用(在尊重任务调度程序,任务创建选项等方面) )。有明确的答案吗?最好的方法是什么?
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;
}