【问题标题】:Asp.Net controller seemingly behaves as if single-threaded. Why?Asp.Net 控制器的行为似乎是单线程的。为什么?
【发布时间】:2022-02-02 16:37:04
【问题描述】:

(以下所有内容最初都是为 .Net 5.0 编写的,但现在针对 .Net 6.0)

考虑将此 Asp.Net 控制器用作 REST Api:

[AllowAnonymous]
[Route("[controller]")]
[ApiController]
[ApiConventionType(typeof(DefaultApiConventions))]
public class DebugController : ControllerBase {

    private readonly ILoggingWrapper log;

    public DebugController(ILoggingWrapper log) {
        this.log = log;
        log.Information("Constructor called");
    }

    private async Task Slow() {
        await Task.Delay(15000).ConfigureAwait(false);
    }

    [Authorize()]
    [HttpGet]
    [Route("testSlow")]
    public async Task<ActionResult> TestSlow() {
        await Slow().ConfigureAwait(false);
        return Ok();
    }

    [Authorize()]
    [HttpGet]
    [Route("testFast")]
    public async Task<ActionResult> TestFast() {
        return Ok();
    }
}

我配置了一个 Swagger 页面,我可以在其中按需调用 TestSlow 和 TestFast。

体验#1

  1. 在 Swagger 页面打开的情况下打开浏览器选项卡,
  2. 只打电话TestSlow

结果

DebugController构造函数立即进入,然后TestSlow立即启动,15秒后返回

经验#2

  1. 在 Swagger 页面打开的情况下打开浏览器选项卡,
  2. 在 Swagger 页面打开的情况下打开另一个浏览器选项卡,
  3. 在第一个 Swagger 页面上,只调用 TestSlow
  4. 快速切换到其他Swagger页面,拨打TestFast

结果

  • DebugController 构造函数立即进入,然后 TestSlow 立即启动
  • 当调用TestFast,而Testslow 仍在运行时,DebugController 构造函数立即进入,TestFast 立即启动。

上述两种体验的行为符合我的预期:Asp.Net 是多线程的,调用一个端点并不会阻止另一个客户端调用另一个端点,即使第一个端点仍在为第一个客户端提供服务。

体验#3(奇怪的体验)

  1. 在 Swagger 页面打开的情况下打开浏览器选项卡,
  2. 在 Swagger 页面打开的情况下打开另一个浏览器选项卡,
  3. 在第一个 Swagger 页面上,仅致电 TestSlow
  4. 快速切换到另一个 Swagger 页面,在那里也可以拨打TestSlow

结果

  • DebugController 构造函数立即进入,然后TestSlow 立即启动
  • 当调用 other TestSlow 时,Controller 的构造器在第一次调用 TestSlow 完全完成并返回之前不会被调用!。实际上,对 TestSlow 的两次调用是按顺序发生的。

为什么会这样?为什么当我尝试调用同一个端点两次时,多线程似乎突然“消失”了,即使我是从两个不同的客户端执行的?

【问题讨论】:

  • 你在发布模式下尝试过同样的实验吗?
  • 您是否尝试过不调试(并使用日志记录/时间测量来确定行为)?
  • 您是否启用了会话状态?如果您看到来自同一浏览器的请求是串行而不是并行提供的,那通常是罪魁祸首。 (注意:同一浏览器中的两个选项卡不是“两个不同的客户端”;请尝试从两个不同的浏览器调用。)
  • 为什么要使用 .ConfigureAwait(false)?这不需要在 ASP.NET Core 应用程序中完成。
  • 这里只是挑剔...“异步”不等于“多线程”。 (不过,对您的问题没有任何改变...... async 应该是一个非阻塞调用。)

标签: c# asp.net swagger-ui .net-6.0


【解决方案1】:

我很可能偶然发现 会话状态 禁用了多次调用同一端点的同时服务,如下所示:

Disable Session state per-request in ASP.Net MVC

所以看起来这不是多线程问题,而是网络应用配置(“设计”)问题。

@Richard 认为:将此作为答案发布,我会将其标记为正确答案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-22
    • 2015-08-03
    • 1970-01-01
    • 2013-10-16
    • 1970-01-01
    • 2014-02-02
    • 1970-01-01
    • 2013-02-06
    相关资源
    最近更新 更多