我有一个异步方法:
public async Task<bool> ValidateRequestAsync(string userName, string password)
{
using (HttpClient client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync(url);
string stringResponse = await response.Content.ReadAsStringAsync();
return bool.Parse(stringResponse);
}
}
我这样称呼这个方法:
bool isValid = await ValidateRequestAsync("user1", "pass1");
我可以使用同步方法调用相同的方法,而不使用await
关键字吗?
例如:
public bool ValidateRequest(string userName, string password)
{
return ValidateRequestAsync(userName, password).Result;
}
我认为这会导致僵局。
修改
调用上面的方法会使调用永远不会结束。 (该方法不再到达终点)
答案 0 :(得分:61)
如果从单线程执行上下文(如UI线程)调用异步方法,并等待同步结果,则死锁的可能性很高。在您的示例中,该概率为100%
想一想。致电
后会发生什么ValidateRequestAsync(userName, password).Result
您调用方法ValidateRequestAsync。在那里你调用ReadAsStringAsync。结果是,任务将返回到UI线程,并且计划继续在UI线程可用时继续执行。但是,当然,它永远不可用,因为它正在等待(阻止)任务完成。但是任务无法完成,因为它正在等待UI线程变得可用。死锁。
有一些方法可以防止这种僵局,但它们都是一个坏主意。为了完整起见,以下内容可能有效:
Task.Run(async () => await ValidateRequestAsync(userName, password)).Result;
这是一个坏主意,因为你仍然阻止你的UI线程等待并且没有任何用处。
那么解决方案是什么呢?一路走异步。 UI线程上的原始调用者可能是一些事件处理程序,因此请确保它是异步的。
答案 1 :(得分:5)
您可以使用return ValidateRequestAsync(userName,password).GetAwaiter()。GetResult();
答案 2 :(得分:0)
对我来说,它在异步调用中使用.ConfigureAwait(false)设置起作用。我有类似
return await Entities.SingleOrDefaultAsync(.....).ConfigureAwait(false);