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

Ela*_*atz 14 c# asp.net-mvc multithreading fiddler asp.net-web-api

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

public string Tester()
{
    Thread.Sleep(2000);

    return "OK";
}
Run Code Online (Sandbox Code Playgroud)

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

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

sis*_*sve 17

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

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

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


Bad*_*dri 8

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

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

现在,我有像你一样的确切的API控制器,我在IIS中托管它.如果我发出并发请求,它会并行运行请求而不是串行运行请求.这是我从Fiddler测试的方式.

首先,我对API进行了GET并等待了200个状态代码(Fiddler左窗格中的#1).然后,我选择#1并按U以无条件重播相同的请求9次.有了这个,我在左窗格中有10个请求(#1到#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;
}
Run Code Online (Sandbox Code Playgroud)

我得到了以下内容.

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
Run Code Online (Sandbox Code Playgroud)

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

  • 没关系,web api没有与会话链接,你正在试验没有会话模式.您可以在启用会话时测试您的方案.然后你必须按顺序而不是并行获得请求.你可以确认一下 (2认同)

Mar*_*gal 5

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

它指出:

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

为了解决这个问题,你可以使用异步方法,如所描述这里.

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

public async Task<MyObj> GetObj()
Run Code Online (Sandbox Code Playgroud)

  • Mark 在他的回答中引用的声明并不完全准确,因为它不适用于实际的 WebApi 解决方案(与在 MVC.NET 解决方案中使用 ApiController 时相反)。将其标记为“正确”可能会误导人们(主要是因为该问题缺乏一些背景信息),让他们相信默认情况下 WebApi 必然依赖于会话状态 - 但事实显然并非如此。另请参阅@Badri 的答案。 (2认同)