【问题标题】:How to make controller action truly async如何使控制器动作真正异步
【发布时间】:2014-02-14 16:44:33
【问题描述】:

我有以下控制器:

public class PingController : ApiController 
{
    [Route("api/ping")]
    [HttpGet]
    public IHttpActionResult Ping()
    {
        var log = HostLogger.Get(typeof(PingController));
        log.Info("Ping called.");
        return Ok("Ping succeeded @ " + DateTime.UtcNow);
    }

    [Route("api/long-ping")]
    [HttpGet]
    public async Task<IHttpActionResult> LongPing(CancellationToken cancelToken)
    {
        await Task.Delay(30 * 1000);
        return Ok("Ping succeeded @ " + DateTime.UtcNow);
    }
}

如果我执行 LongPing,然后在不同的浏览器选项卡中执行 Ping,Ping 将在 LongPing 执行之前执行并返回——这正是我正在寻找的。问题是当我执行两个 LongPing 调用时,第二个调用大约需要 60 秒才能完成(不是 30 秒)。 Chrome 报告第二个调用的延迟为 58 秒(60 秒减去我开始第二个请求所用的时间)。在我看来,如果我能正常工作,两个 LongPing 调用应该在 30 秒左右执行。

我还应该提到我在 OWIN 托管环境中托管它,而不是 IIS。但我不认为这有什么不同,但也许有人会证明我错了。

如何使 LongPing 的行为真正像异步请求一样?

【问题讨论】:

  • 禁用会话状态
  • 如果这是使用托管在 IIS 中的标准 MVC,我可能会同意。但这是一个使用 WebAPI 的控制台托管 OWIN 应用程序,默认情况下没有会话(我认为这是正确的)。

标签: c# async-await asp.net-web-api2


【解决方案1】:

很可能是您的会话状态导致了您的问题。对于这种行为有一个冗长的解释,但简短的版本是特定用户会话一次只能执行一个请求,因为会话状态锁定以确保一致的状态。如果您想加快速度,请禁用 cookie 以测试会话状态假设(这样每个请求您将获得 1 个会话状态),或禁用应用程序中的会话状态。否则,您的代码是 a-ok 异步明智的。

【讨论】:

    【解决方案2】:

    原来这是 Chrome 在调用同一个 URL 时的行为。在使用 Chrome 进行测试时,我总是忘记这一点。通常我用 Fiddler 进行测试,但是这个 VM 没有 Fiddler。

    请参阅此 SO 问答: Chrome treating smart url and causing concurrent requests pend for each other

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-14
      • 2013-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-04
      • 1970-01-01
      相关资源
      最近更新 更多