为什么这个web api控制器不兼容?

我有一个Web API控制器,里面有以下方法:

public string Tester() { Thread.Sleep(2000); return "OK"; } 

当我调用它10次(使用Fiddler)时,我希望所有10个调用在~2秒后返回。 然而,呼叫分别在2,4,8 …… 20秒后返回。 什么阻止它同时运行? 我该如何解决这个问题?

常规控制器的行为与web-api控制器相同吗?

您描述的内容与ASP.NET会话状态的默认行为相匹配,可以通过在web.config中禁用它来解决。

对会话状态的访问是每个会话独占的,这意味着如果两个不同的用户发出并发请求,则同时授予对每个单独会话的访问权限。 但是,如果对同一会话发出两个并发请求(通过使用相同的SessionID值),则第一个请求将获得对会话信息的独占访问权。 第二个请求仅在第一个请求完成后执行。 (如果由于第一个请求超过锁定超时而释放信息的独占锁定,则第二个会话也可以访问。)如果@ Page指令中的EnableSessionState值设置为ReadOnly,则只读请求会话信息不会导致会话数据的独占锁定。 但是,会话数据的只读请求可能仍然必须等待由会话数据的读写请求设置的锁定才能清除。

来源: ASP.NET会话状态概述

我不认为我在回答你的问题,但我想在这里写的内容太大而无法发表评论。

首先,ASP.NET Web API与会话状态无关。 实际上,如果会话必须与Web API一起使用,则需要明确启用它。

现在,我和你一样拥有完全相同的API控制器,并在IIS中托管它。 如果我发出并发请求,它将并行运行请求而不是串行运行请求。 这是我从Fiddler测试的方式。

首先,我对API进行了GET并等待了200个状态代码(Fiddler左窗格中的#1)。 然后,我选择#1并按U以无条件重播相同的请求9次。 有了这个,我在左窗格(#1到#10)中有10个请求。 然后,我选择了所有10个并按下R并行地重新发出所有10个请求。 然后,我在左侧窗格中选择了请求11到20,然后转到“时间线”选项卡。 我看到这张图。

PS。 我测试了本地运行的Web API,BTW。

在此处输入图像描述

接下来,我想记录action方法收到的时间戳请求。 所以,我修改了action方法来返回这样的字符串。

 public string Get() { string ts = DateTime.Now.ToString("mm:ss.fff"); Thread.Sleep(2000); return ts; } 

我得到了以下内容。

 00:43.795 00:43.795 00:45.812 00:44.517 00:43.795 00:43.795 00:45.515 00:43.795 00:43.795 00:43.795 

对我来说,这意味着,所有请求都是并行运行的。

看看这个问题,这个问题与您的问题有关: 所有Web请求是并行执行还是异步处理?

它指出:

默认情况下,webApi服务并行执行所有传入请求,但前提是当前多个请求(在特定时间)来自不同的会话。 也就是说,如果单个客户端将同时向服务器发送一些请求,则所有这些请求将按顺序执行,并且不会同时执行。

要解决此问题,您可以使用异步方法,如此处所述。

通常,您需要将方法声明为异步,如下所示:

 public async Task GetObj() 

请尝试使用此代码:

 public async Task Tester() { await Task.Delay(2000); return "OK"; } 

请参阅此内容以了解Task.Delay与Thread.Sleep之间的区别,它阻止了http://social.technet.microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs-task-delay。 ASPX

您必须已为Web Api启用了Session State 。 Web API默认是restful,没有会话。 检查你的global.asax Application_AuthenticateRequest部分(这是我为Web Api启用会话状态的地方)。 找到启用会话状态的位置,并将其设置为只读模式,以允许使用会话状态在Web方法上实现并行。 请参阅以下类似的问题: Web API服务 – 如何使服务器上的请求同时执行

寻找这样的东西:

 HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required); 

把它改成这个:

 HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.ReadOnly);