Asp.net web api HttpWebRequest异步与开始/结束
我有一个Web API项目,其控制器反过来向第三方REST接口发出Web请求。我的控制器CRUD函数已标记为async,但实现方式是使用HttpWebRequest阻塞函数GetRequestStream和GetResponse 这是否合适,或者我也应该使用HttpWebRequest的Begin/End方法。这似乎有些过分,因为它将异步一个已经异步的操作,或者它将允许更多并发的传出web请求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
正在寻找传入和传出吞吐量的最佳解决方案。我建议您保留异步方法,并使用而不是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++库,它显然不支持异步(使用卷曲),那么什么是最好的方法?如果不是异步的,并且不能使它真正地异步,那么只需同步调用它即可。