我有这个异步方法:
public async Task<RES> PostAsync<RES>(string url, string content) where RES : new()
{
using (var client = new HttpClient())
{
HttpResponseMessage message = await client.PostAsync(url, new StringContent(content, Encoding.UTF8, "application/json"));
var readAsStringAsync = await message.Content.ReadAsStringAsync();
return await readAsStringAsync.FromJsonAsync<RES>(mySerializerSettings);
}
}
其中 FromJsonAsync
作为扩展方法实现:
public async static Task<T> FromJsonAsync<T>(this string data, JsonSerializerSettings settings) where T : new()
{
return (T)(await JsonConvert.DeserializeObjectAsync<T>(data, settings));
}
现在我想添加一个常规的同步 Post
方法,我认为实现将是:
public RES Post<RES>(string url, string content) where RES : new()
{
return PostAsync<RES>(url, content).Result;
}
但这并不真的有效。我看到请求是通过 Http 嗅探器发送的,我得到了回复,但我在调试时卡住了,无法继续。
顺便说一句,这确实有效(使用Result
而不是await
):
public RES Post<RES>(string url, string content) where RES : new()
{
using (var client = new HttpClient())
{
HttpResponseMessage message = client.PostAsync(url, new StringContent(content, Encoding.UTF8, "application/json")).Result;
var readAsStringAsync = message.Content.ReadAsStringAsync().Result;
return readAsStringAsync.FromJson<RES>(mySerializerSettings);
}
}
其中 FromJson
作为扩展方法实现:
public static T FromJson<T>(this string data, JsonSerializerSettings settings) where T : new()
{
return (T)JsonConvert.DeserializeObject<T>(data, settings);
}
该应用程序是一个网络后端 (WebApi)。
我做错了什么?
最佳答案
您的手上可能遇到了死锁。
Asp.net 使用 SynchronizationContext
将延续发布回请求上下文。如果上下文被阻塞(就像您在 PostAsync<RES>(url, content).Result
上的情况一样),则无法执行继续操作,因此异步方法无法完成,您会遇到死锁。
您可以使用 ConfigureAwait(false)
来避免它:
public async Task<RES> PostAsync<RES>(string url, string content) where RES : new()
{
using (var client = new HttpClient())
{
HttpResponseMessage message = await client.PostAsync(url, new StringContent(content, Encoding.UTF8, "application/json"));
var readAsStringAsync = await message.Content.ReadAsStringAsync().ConfigureAwait(false);
return await readAsStringAsync.FromJsonAsync<RES>(mySerializerSettings).ConfigureAwait(false);
}
}
但是最好避免在异步代码上同步阻塞,并为同步和异步设置两个不同的版本。
关于c# - 通过调用 <asyncmethod>.Result 实现同步方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32608947/