我将代码部署到生产服务器时出现问题。它不会在我的计算机上本地发生。当我运行该行
var host = await Dns.GetHostEntryAsync(adresse);
生产环境冻结或等待无限期。为什么会这样?
以下是代码:
public async Task<string> HentAsync(string ip)
{
if (string.IsNullOrWhiteSpace(ip) || kLoopbackIp.Contains(ip))
{
return string.Empty;
}
if (IpHostname.ContainsKey(ip))
{
UpdateAndRemoveOldElements(ip);
return IpHostname[ip].Item1;
}
try
{
IPAddress adresse = IPAddress.None;
if (!IPAddress.TryParse(ip, out adresse))
{
return string.Empty;
}
var host = await Dns.GetHostEntryAsync(adresse);
string hostname = host.HostName;
IpHostname.AddOrUpdate(ip,
new Tuple<string, DateTime>(hostname, DateTime.Now),
(x, y) => new Tuple<string, DateTime>(hostname, DateTime.Now));
return hostname;
}
catch (Exception)
{
// Tar i mot exception og returnerer tom string
return string.Empty;
}
}
更新: async方法就像这样从一个同样的方法调用(这可能是罪魁祸首)。
public string Hent(string ip)
{
return HentAsync(ip).Result;
}
答案 0 :(得分:1)
最可能的原因是此调用的来源在UI线程上运行;也许调用Hent()
更新UI元素?
此问题已在此处详细记录:await works but calling task.Result hangs/deadlocks
Hent()
拨打HentAsync()
,然后拨打await Dns.GetHostEntryAsync()
。这最后一个调用产生一个新线程,但想要在完成后返回调用线程,在这种情况下是UI线程,但它不能这样做,因为.Result
蹲在线程上而不是让它产生它暂时与await
一样。
正如@spender和@Dirk所指出的,一个解决方案是将.ConfigureAwait(false)
添加到await Dns.GetHostEntryAsync()
。实际上,您应该将此添加到您不关心函数继续的线程上下文的每个await
。
这种方法仍然非常脆弱,因为任何时候你忘记这样做或执行采用未经修改的await
的路径,问题将再次发生。最好的选择是使每个函数调用产生顶级UI线程函数async
然后await
,这可能会导致延迟。这是async / await的规范用例,导致平坦,易于遵循的代码,几乎没有死锁的可能性。