ASP.NET MVC AsyncController和IO绑定请求

本文关键字:IO 绑定 请求 AsyncController NET MVC ASP | 更新日期: 2023-09-27 18:26:03

我有一个AsyncController和一个主页,它可以查询用户的朋友列表并与他们一起进行一些数据库工作。我为任何调用外部web服务的请求实现了异步操作方法模式。这是处理这种情况的有效方法吗?在请求量很高的时候,我看到IIS有时线程不足,我担心我的嵌套异步魔法可能会以某种方式参与其中。

我的主要问题/谈话要点是:

  • 在异步控制器操作中嵌套IAsyncResult异步web请求是否安全?或者这只是在某个地方加倍负荷
  • 使用ThreadPool.RegisterWaitForSingleObject来处理长时间运行的web请求的超时是否有效,或者这会吃掉ThreadPool线程并耗尽应用程序的其余部分
  • 只在异步控制器操作中执行同步web请求会更高效吗

示例代码:

public void IndexAsync() 
{
    AsyncManager.OutstandingOperations.Increment();
    User.GetFacebookFriends(friends => {
        AsyncManager.Parameters["friends"] = friends;
        AsyncManager.OutstandingOperations.Decrement();
    });
}
public ActionResult IndexCompleted(List<Friend> friends)
{
    return Json(friends);
}

User.GetFacebookFriends(Action<List<Friend>>)看起来像这样:

void GetFacebookFriends(Action<List<Friend>> continueWith) {
    var url = new Uri(string.Format("https://graph.facebook.com/etc etc");
    HttpWebRequest wc = (HttpWebRequest)HttpWebRequest.Create(url);
    wc.Method = "GET";
    var request = wc.BeginGetResponse(result => QueryResult(result, continueWith), wc);
    // Async requests ignore the HttpWebRequest's Timeout property, so we ask the ThreadPool to register a Wait callback to time out the request if needed
    ThreadPool.RegisterWaitForSingleObject(request.AsyncWaitHandle, QueryTimeout, wc, TimeSpan.FromSeconds(5), true);
}

QueryTimeout只会在超过5秒的时间内中止请求。

ASP.NET MVC AsyncController和IO绑定请求

您首先描述的完全异步方法是最好的,因为这会将TP线程释放回池中以供重用。很有可能你正在其他地方执行一些其他的阻塞操作。QueryResponse中发生了什么?虽然异步获取响应,但是否也异步读取响应流?如果没有,就这样做,那么TP饥饿应该减少。