如何使控制器动作真正异步

时间:2014-02-14 16:44:33

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

我有以下控制器:

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调用都应该在30s左右执行。

我还应该提一下,我是在OWIN托管环境中托管这个,而不是IIS。但我认为这没有任何区别,但也许有人会证明我错了。

如何使LongPing表现得像异步请求一样?

2 个答案:

答案 0 :(得分:1)

您的会话状态很可能导致您的问题。对于此行为有一个冗长的解释,但简短版本是特定用户会话一次只能执行一个请求,因为会话状态锁定以确保一致状态。如果要加快速度,请禁用cookie以测试会话状态假设(每个请求将获得1个会话状态),或者禁用应用程序中的会话状态。你的代码在其他方面是不正确的。

答案 1 :(得分:1)

事实证明这是Chrome在调用相同网址时的行为。在使用Chrome进行测试时,我总是忘记这一点通常我用Fiddler测试,但是这个VM没有Fiddler。

见SO Q&amp; A: Chrome treating smart url and causing concurrent requests pend for each other