如果我在.net web api
中运行此代码public class ConfigurationApiClient : IConfigurationService
{
private readonly HttpClient _client;
public ConfigurationApiClient(IConfigurationManager configurationManager)
{
;
_client = new HttpClient();
_client.BaseAddress = new Uri(configurationManager.GetAppSetting("ApiUrl"));
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public Configuration GetConfiguration(int agentId)
{
return GetConfigurationAsync(agentId).Result;
}
private async Task<Configuration> GetConfigurationAsync(int agentId)
{
try
{
var response = await _client.GetAsync("resource").ConfigureAwait(false);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsAsync<Configuration>();
}
catch (HttpRequestException ex)
{
throw new Exception(string.Format("Exception when getting configuration for agent: {0}", agentId), ex);
}
}
}
我依靠ConfigureAwait(false)
使它成功,如果我删除它进入死锁。
但是,如果基于此example,我会在控制台应用程序中编写与之前相同的内容
class Program
{
static void Main()
{
var product = RunAsync().Result;
}
static async Task<Product> RunAsync()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:8080/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// New code:
HttpResponseMessage response = await client.GetAsync("api/resource");
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadAsAsync<Product>();
}
else
{
return null;
}
}
}
}
即使我读到ConfigureAwait(false)
我也不清楚为什么它在控制台中工作而不在api中。
答案 0 :(得分:2)
除非SynchronizationContext.Current
另有说明,否则使用等待捕获ConfigureAwait(false)
。当await之后的代码恢复时,它会被发布到该上下文中。在UI应用程序中,这意味着在单个UI线程上运行。在asp.net应用程序(您的情况)中,它在原始请求的上下文中运行。
控制台应用程序没有任何SynchronizationContext
开头,所以你不能开始死锁。
您可以通过查看SynchronizationContext.Current
但是,使用ConfigureAwait(false)
只能用作最后一项措施。大多数情况下,您希望避免阻塞异步代码。