我发现.NET Framework的HttpClient类/对象与VS-2013 Project PhotoServer(DLL)类/对象之间存在有趣的区别。这让我想知道脚本是否存在错误。
我正在使用.NET Framework v4.5.1。
我在同步Web通用处理程序中使用HttpClient脚本。注意,我正在使用“ .Result”进行异步POST以等待响应。因此,查看有效的HttpClient是
using (var httpClient = new HttpClient())
{
var response = httpClient.PostAsync(
_baseUrl,
new FormUrlEncodedContent
(
new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("Vin", parmVin),
new KeyValuePair<string, string>("ImageSize", parmImageSize)
}.ToArray()
)
).Result;
//returned string[] datatype...
var photoUrls = response.Content.ReadAsStringAsync().Result;
}
我正在同步Web通用处理程序中使用“ GetPhotoUrlsAsync”脚本。此“ GetPhotoUrlsAsync”对象来自Project类(DLL)。同样,我使用的是“ .Result”,它不起作用,只是死锁并挂起。我想知道为什么会这样,并且脚本中有错误吗?
//[Scripts in Web Generic Handlers]...
var managerVehiclePhoto = new ManagerVehiclePhoto();
var photoUrls = managerVehiclePhoto.GetPhotoUrlsAsync("12345678901234567").Result;
//[Project Class]...
namespace BIO.Dealer.Integration.PhotoServer
{
public seal class VehiclePhotoManager
{
public async Task<string[]> GetPhotoUrlsAsync(string vin)
{
var listResponse = await _client.ListAsync(vin);
return listResponse.ToArray();
}
}
}
谢谢...
编辑#1
//Synchronous API Call...
public string[] GetPhotoUrls(string vin)
{
return GetPhotoUrlsAsync(vin).Result;
}
.Result
在这两种情况下,这样使用实际上是一个错误。它只是在这种HttpClient
情况下不会死锁。请注意,如果像这样使用HttpClient
,则其他平台(尤其是Windows Phone,IIRC)上的相同库将死锁。
我在博客上详细描述了僵局,但是要点是:
每次使用时,默认情况下都会捕获一个ASP.NET“请求上下文” await
。当该async
方法恢复时,它将在该上下文中恢复。但是,诸如此类HttpContext
不是多线程安全的,因此ASP.NET一次只能将该上下文限制为一个线程。因此,如果您通过调用.Result
来阻塞线程,那么它将阻塞该上下文中的线程。
GetPhotoUrlsAsync
死锁的原因是因为它是一个async
试图在该上下文中恢复的方法,但是在该上下文中已经有一个线程被阻塞。之所以HttpClient
起作用,是因为GetAsync
等实际上不是async
方法(请注意,这是一个实现细节,您不应依赖此行为)。
解决这个问题的最好办法是更换.Result
有await
:
var managerVehiclePhoto = new ManagerVehiclePhoto();
var photoUrls = await managerVehiclePhoto.GetPhotoUrlsAsync("12345678901234567");
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句