Asp.net web api HttpWebRequest异步与开始/结束

Asp.net web api HttpWebRequest异步与开始/结束,asp.net-web-api,httpwebrequest,Asp.net Web Api,Httpwebrequest,我有一个Web API项目,其控制器反过来向第三方REST接口发出Web请求。我的控制器CRUD函数已标记为async,但实现方式是使用HttpWebRequest阻塞函数GetRequestStream和GetResponse 这是否合适,或者我也应该使用HttpWebRequest的Begin/End方法。这似乎有些过分,因为它将异步一个已经异步的操作,或者它将允许更多并发的传出web请求 正在寻找传入和传出吞吐量的最佳解决方案。我建议您保留异步方法,并使用而不是HttpWebRequest

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

这是否合适,或者我也应该使用HttpWebRequest的Begin/End方法。这似乎有些过分,因为它将异步一个已经异步的操作,或者它将允许更多并发的传出web请求


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

我建议您保留异步方法,并使用而不是HttpWebRequest,因为它也支持异步调用

让我们看一个汽车控制器调用第三方服务的伪示例

 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);
        }

}
公共类汽车控制器:ApiController
{
[路线(“cars/{id}”)]
公共异步任务Get(int-id)
{
//凭身份证买车
HttpClient=新的HttpClient();
//直接阅读内容
字符串结果=等待客户端。GetStringAsync(“http://www.google.com");
//处理从第三方REST服务返回的结果
返回Ok(结果);
}
}
如您所见,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);

        }
[Route(“responsecars/{id}”)]
公共异步任务GetResponseStream(int id)
{
HttpClient=新的HttpClient();
HttpResponseMessage responseMessage=等待客户端。GetAsync(“http://www.google.com,HttpCompletionOption.ResponseContentRead);
HttpContent=responseMessage.content;
//使用ReadAsync方法之一
字符串文本=等待内容。ReadAsStringAsync();
返回Ok(文本);
}

希望有此帮助。

服务器上的异步与客户端上的异步是独立的

您可以使用从客户端异步调用同步Web API方法,也可以使用
WebRequest.GetResponse
从客户端同步调用异步Web API方法,或者您可以在两侧使用异步,这可能是最好的方法。您不需要使用
Begin/End
APM风格的
WebRequest
api,除非您将.NET4.0作为客户端的目标。改用基于
任务的异步API

在这两种情况下,当Web API控制器方法完全完成时,将向客户端发送完整的HTTP请求,而不管它是以同步还是异步方式实现的(
Task
-based)

控制器标记为异步,但实现使用同步HttpWebRequest调用,因为我的控制器正在等待Task.Run(同步web请求)

想想请求中发生了什么。请求进入,ASP.NET使用线程池线程来处理请求。控制器操作将工作排队到线程池(占用另一个线程),然后等待该工作,释放原始请求线程。使用
wait
没有获得任何好处,因为web请求上仍然存在线程池线程阻塞

因此,您几乎不应该在ASP.NET上使用
Task.Run
(或将工作队列排入线程池的任何其他方法)

这是否合适,或者我也应该使用HttpWebRequest的Begin/End方法。这似乎有些过分,因为它将异步一个已经异步的操作

现在它不是真正的异步的;仍然有一个线程被阻塞。我将这种技术称为“队列阻塞线程池线程的工作,然后等待它”假异步技术

合适的修复方法是使用
HttpClient
,它是为异步使用而设计的;或者,你可以使用

但我不明白的是,如果我使用wait-HttpClient.SendAsync,那么肯定有什么东西在阻塞等待响应


不,不一定有什么东西挡住了。正如我在博客中所描述的,在真正的异步场景中(即,不是伪异步),。

是正确的,但它有任何好处吗。如果我的控制器已经对第三方接口进行了异步调用,那么使这些调用也异步是否还有其他好处,或者实际上增加了额外的开销?您好,肯定有好处!因为如果调用花费大量时间,服务器可以释放当前线程来处理其他请求。您说您将那些方法标记为
async
,但正在使用阻塞方法?仅仅因为一个方法被标记为
async
,并不意味着它是异步的;特别是,如果不使用
wait
,则它是同步的(检查警告消息)。是的,控制器标记为异步,但实现使用同步HttpWebRequest调用,因为我的控制器正在等待任务。运行(同步web请求)。所以我猜发生的是,我收到了很多异步传入请求,这些请求都在排队等待同步出站请求?但我不明白的是,如果我使用Wait HttpClient.SendAsync,那么在某个地方一定有什么东西在阻止等待响应,如果我有一个4核的盒子但有100个请求,那么使用SendAsync如何帮助我的出站吞吐量?好吧,很酷,所以我已经更改了代码,以便我的控制器等待我的HttpClient异步调用。最后,我还有一个要求,使用一个第三方C++库,它显然不支持异步(使用卷曲),那么什么是最好的方法?如果不是异步的,并且不能使它真正地异步,那么只需同步调用它即可。