使用 HttpClient 时避免从异步函数返回类型 Task<Object>
Avoid returning type Task<Object> from an async function when using HttpClient
我正在使用 System.Net.Http.HttpClient
进行 HTTP 调用。看来所有的调用都必须是异步的。
假设我的项目结构如下:
MVC Web 应用程序 -> 业务层 -> 数据层
在数据层中,我对 Web API 进行 HTTP 调用以获取 return 数据,我最终使用了如下函数:
public async Task<IList<Product>> GetProducts()
{
HttpResponseMessage response = await client.GetAsync("api/products");
string data = await response.Content.ReadAsStringAsync();
IList<Product> products = JsonConvert.DeserializeObject<IList<Product>>(data);
return products;
}
然后进入业务层:
public Task<IList<Product>> GetProducts(string name = null)
{
return _repository.GetProducts(name);
}
最后在 MVC 控制器中:
public IActionResult Index()
{
Task<IList<Product>> ProductsTask = _manager.GetProducts();
IList<Product> ProductsNonTask = products.Result.ToList();
return View();
}
我真的必须让每个函数 return 成为指向我的 MVC 控制器的类型 Task<IList<Product>>
的列表吗?正如您在 MVC 控制器中看到的那样,我必须首先使用围绕它们的 Task 来检索产品。当我通过它查看产品列表时,调试器看起来有点奇怪。因此,正如您所见,我将它们转换为常规产品列表。
我想知道让我的所有函数 return 键入 Task<IList<Product>>
一直到我的 MVC 控制器是否是正确的做法,或者是否有解决方法以便我的功能仍然可以 return 产品的标准列表,但继续使用 HttpClient
?
的异步功能
更新:执行以下操作有什么问题吗:
public IList<Product> GetProducts()
{
Task<HttpResponseMessage> response = client.GetAsync("api/products");
if (response.Result.IsSuccessStatusCode)
{
string data = response.Result.Content.ReadAsStringAsync().Result;
IList<Product> products = JsonConvert.DeserializeObject<IList<Product>>(data);
retVal = products;
}
}
如果您希望操作实际上是异步的,则需要一直异步。
当您用 Wait
或 Result
阻塞 Task
时,它就不再是异步的了。
所以,没有。要么一直使用异步,要么根本不使用它。
I wonder... if there is a workaround so that my functions can still return the a standard list of product but continue to use the async capabilities of the HttpClient?
不,真的没有。
您可能应该让您的代码异步,因为它在可伸缩性和性能方面有很多好处。但如果您反对这样做,您可以使用具有同步网络操作的 WebClient
。
Do I really have to make every single function return a list of type Task> leading up to my MVC controller?
是的,你必须这样做,但你甚至没有抓住所有地方,因为 Index
本身也必须是异步的。
异步真的很有感染力。必要时使用,默认情况下不使用。
我正在使用 System.Net.Http.HttpClient
进行 HTTP 调用。看来所有的调用都必须是异步的。
假设我的项目结构如下: MVC Web 应用程序 -> 业务层 -> 数据层
在数据层中,我对 Web API 进行 HTTP 调用以获取 return 数据,我最终使用了如下函数:
public async Task<IList<Product>> GetProducts()
{
HttpResponseMessage response = await client.GetAsync("api/products");
string data = await response.Content.ReadAsStringAsync();
IList<Product> products = JsonConvert.DeserializeObject<IList<Product>>(data);
return products;
}
然后进入业务层:
public Task<IList<Product>> GetProducts(string name = null)
{
return _repository.GetProducts(name);
}
最后在 MVC 控制器中:
public IActionResult Index()
{
Task<IList<Product>> ProductsTask = _manager.GetProducts();
IList<Product> ProductsNonTask = products.Result.ToList();
return View();
}
我真的必须让每个函数 return 成为指向我的 MVC 控制器的类型 Task<IList<Product>>
的列表吗?正如您在 MVC 控制器中看到的那样,我必须首先使用围绕它们的 Task 来检索产品。当我通过它查看产品列表时,调试器看起来有点奇怪。因此,正如您所见,我将它们转换为常规产品列表。
我想知道让我的所有函数 return 键入 Task<IList<Product>>
一直到我的 MVC 控制器是否是正确的做法,或者是否有解决方法以便我的功能仍然可以 return 产品的标准列表,但继续使用 HttpClient
?
更新:执行以下操作有什么问题吗:
public IList<Product> GetProducts()
{
Task<HttpResponseMessage> response = client.GetAsync("api/products");
if (response.Result.IsSuccessStatusCode)
{
string data = response.Result.Content.ReadAsStringAsync().Result;
IList<Product> products = JsonConvert.DeserializeObject<IList<Product>>(data);
retVal = products;
}
}
如果您希望操作实际上是异步的,则需要一直异步。
当您用 Wait
或 Result
阻塞 Task
时,它就不再是异步的了。
所以,没有。要么一直使用异步,要么根本不使用它。
I wonder... if there is a workaround so that my functions can still return the a standard list of product but continue to use the async capabilities of the HttpClient?
不,真的没有。
您可能应该让您的代码异步,因为它在可伸缩性和性能方面有很多好处。但如果您反对这样做,您可以使用具有同步网络操作的 WebClient
。
Do I really have to make every single function return a list of type Task> leading up to my MVC controller?
是的,你必须这样做,但你甚至没有抓住所有地方,因为 Index
本身也必须是异步的。
异步真的很有感染力。必要时使用,默认情况下不使用。