我在域名服务中有以下代码:
HttpClient client = new HttpClient();
client.GetAsync("http://somewebsite.com").Result;
哪个工作正常,我可以在跟随的线上设置一个断点,它们确实击中了,一切都很好。但是,我在同一个项目中安装的nuget包中有相同的代码行。那里有完全相同的http电话:
public class Client : Base
{
public Task<List<Stuff>> GetAsync()
{
return SendMessageAsync(HttpMethod.Get, "http://getstuff.com")
.ContinueWith(x => JsonConvert.DeserializeObject<List<StuffView>>(x.Result.Content.ReasAsStringAsync().Result);
}
}
public class Base
{
HttpClient client:
public Base(HttpClient client)
{
this.client = client:
}
protected async Task<HttpResponseMessage> GetMessageAsync(BttpMethod method, string url)
{
var request = CreateRequestAsync(method, url);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.SendAsync(request); //line 1
return response; // Line 2
}
protected HttpRequestMessage CreateRequestAsync(HttpMethod method, string url)
{
var request = new HttpRequestMessage(method, url);
request.SetBearerToken(myAccessTokenProvider);
return request;
}
}
这是我的域名服务使用nuget包代码的方式:
var client = factory.Create();
client.GetAsync().Result;
调试此代码显示内部基类行1被命中,但第2行永远不会。在互联网上搜索似乎是一个线程死锁问题。所以我的问题是,假设它是一个死锁,为什么域服务中的第一个http调用工作,但不是第二个使用nuget包代码?#/ p>
HttpClient死锁问题: HttpClient.GetAsync(...) never returns when using await/async
答案 0 :(得分:2)
第一个示例有效,因为任务在您调用.Completed == true
之前处于.Result
状态,或者该行代码具有SyncronisationContext.Current == null
。
如果任务未处于已完成状态,则在您调用.Result
或{.Wait()
时,如果SyncronisationContext.Current != null
调用.Result
或.Wait()
,则可能会导致死锁{1}}。最好的办法是将整个调用堆栈标记为async
并开始返回Task
而不是void
和Task<T>
,然后返回T
,然后调用{{} 1}}在您使用await
或.Result
的所有地方。
如果您不愿意更改这些代码,则必须切换到使用非异步方法,这将要求从.Wait()
切换到HttpClient
并使用非异步方法调用来执行您的请求。
答案 1 :(得分:1)
请勿使用.Result
。使用.Result
,I / O启动(异步),调用线程(同步)阻止等待它完成。
只需使用await
。
var stuff = await client.GetAsync();