HttpWebRequest异步与开始/结束

时间:2014-04-27 23:47:27

标签: asp.net-web-api httpwebrequest

我有一个Web API项目,其控制器反过来向第三方REST接口发出Web请求。我的控制器CRUD函数我已标记为异步,但实现是这样的,我使用HttpWebRequest阻塞函数GetRequestStream和GetResponse。

这是合适的还是我应该使用HttpWebRequest的Begin / End方法。这似乎有点过分,因为它会使异步操作异步,或者是否允许更多的并发传出Web请求?

寻找传入和传出吞吐量的最佳解决方案。

3 个答案:

答案 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