Jon*_*s T 10 .net c# synchronization asynchronous async-await
我知道有些人会争论“为什么不将 SyncMethod() 设为异步方法呢?”。我们希望如此,但在现实世界中,有时出于向后兼容性的原因,我们必须保持 SyncMethod 的原样。
情况是这样的。下面的代码导致我们陷入僵局。
public void SyncMethod()
{
var serviceResult = ProcessDataAsync().Result;
}
public await ServiceResult ProcessDataAsync()
{
//Do other things
await GetDataFromApiAsync();
}
private static HttpClient Client = new HttpClient();
public await ApiResult GetDataFromApiAsync()
{
var response = await Client.GetAsync("http://api.com/getJson");
dynamic obj = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
return obj;
}
Run Code Online (Sandbox Code Playgroud)
选项 1:使用 Task.Run 并获取 task.Result。这解决了死锁问题,但它被迫在原始线程的同步上下文之外的新线程中运行。然而,在某些环境中这是非常不明智的:特别是 Web 应用程序。这是一个好的做法吗?
public void SyncMethod()
{
Task<decimal> task = Task.Run<decimal>(async () => await ProcessDataAsync());
var serviceResult = task.Result;
}
Run Code Online (Sandbox Code Playgroud)
Optoin 2:从 Sync 一直添加到最后一个异步方法。
public void SyncMethod()
{
var serviceResult = GetDataFromApiAsync().ConfigureAwait(false).GetAwaiter().GetResult();;
}
public await ServiceResult ProcessDataAsync()
{
//Do other things
await GetDataFromApiAsync().ConfigureAwait(false);
}
private static HttpClient Client = new HttpClient();
public await ApiResult GetDataFromApiAsync()
{
var response = await Client.GetAsync("http://api.com/getJson").ConfigureAwait(false);
dynamic obj = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync().ConfigureAwait(false));
return obj;
}
Run Code Online (Sandbox Code Playgroud)
选项 3:Stephen Cleary的答案。
public void SyncMethod()
{
var serviceResult = GetDataFromApiAsync().(sync: true).GetAwaiter().GetResult();
}
Run Code Online (Sandbox Code Playgroud)
所有这些解决方案都将解决死锁问题。我的问题是最佳实践是什么?