我有一个Web API项目,其控制器反过来向第三方REST接口发出Web请求。我的控制器CRUD函数我已标记为异步,但实现是这样的,我使用HttpWebRequest阻塞函数GetRequestStream和GetResponse。
这是合适的还是我应该使用HttpWebRequest的Begin / End方法。这似乎有点过分,因为它会使异步操作异步,或者是否允许更多的并发传出Web请求?
寻找传入和传出吞吐量的最佳解决方案。
答案 0 :(得分:0)
我建议您保留异步方法,并使用HttpClient代替HttpWebRequest,因为它也支持异步调用。
让我们看一下调用第三方服务的CarsController的伪示例。
public class CarsController : ApiController
{
[Route("cars/{id}")]
public async Task<IHttpActionResult> Get(int id)
{
//Get a car by its id
HttpClient client = new HttpClient();
//Read the content directly
string result = await client.GetStringAsync("http://www.google.com");
//process the result returns from the thrid party REST service
return Ok(result);
}
}
如您所见,HttpClient支持通过GetXXXAsync()方法异步读取String / Stream / ByteArray。
如果要访问底层响应内容,可以使用以下代码实现:
[Route("responsecars/{id}")]
public async Task<IHttpActionResult> GetResponseStream(int id)
{
HttpClient client = new HttpClient();
HttpResponseMessage responseMessage =await client.GetAsync("http://www.google.com", HttpCompletionOption.ResponseContentRead);
HttpContent content = responseMessage.Content;
//using one of the ReadAsync methods
string text =await content.ReadAsStringAsync();
return Ok(text);
}
希望得到这个帮助。
答案 1 :(得分:0)
服务器上的异步是独立的,与客户端上的异步无关。
您可以使用WebRequest.GetResponseAsync
从客户端调用同步 Web API方法异步,也可以调用异步 Web来自客户端WebRequest.GetResponse
的API方法同步,或者您可以在双方都有异步,这可能是最好的方法。除非您在客户端上使用.NET 4.0,否则不需要使用Begin/End
APM样式的WebRequest
API。改为使用基于Task
的异步API。
在任何一种情况下,当您的Web API控制器方法完全完成时,将向客户端发送完整的HTTP请求,无论它是以同步还是异步(Task
为基础)实现。
答案 2 :(得分:0)
控制器被标记为异步但实现使用同步HttpWebRequest调用,因为我的控制器正在等待Task.Run(同步web请求)
考虑请求中发生的事情。请求进来,ASP.NET采用线程池线程来处理请求。控制器操作将工作排队到线程池(占用另一个线程),然后await
工作,释放原始请求线程。您还没有使用await
获得任何收益,因为在网络请求中仍有线程池线程阻塞。
出于这个原因,你几乎永远不会在ASP.NET上使用Task.Run
(或队列工作到线程池的任何其他方法)。
这是合适的还是我应该使用HttpWebRequest的Begin / End方法。这似乎有点过分,因为它会使已经异步的操作异步
现在不是真的异步;还有一个线程被阻止了。我把这个&#34;队列阻塞工作称为线程池线程,然后等待它#34;技术假异步。
适当的解决方法是使用专为异步使用而设计的HttpClient
;或者,可以使用TaskFactory<T>.FromAsync
to wrap the Begin
/End
methods into an awaitable task。
我不明白的事情是,如果我使用等待HttpClient.SendAsync然后某处必须阻止等待响应
不,没有必要阻止某个地方。正如我在博客中描述的那样,在一个真正的异步场景中(即,不是假的 - 异步),there is no thread。