使用 IIS 时 CancellationToken 不触发

CancellationToken not Triggering when using IIS

我知道像这样的问题已经被问过很多次了,但是 none 提供的答案解决了我的特殊问题。所以我再试一次,自己问一个问题。

我正在开发 ASP.NET 核心 Web 应用程序 运行ning net461(也尝试过 net48),我在其中定义了这样的 HTTP 端点:

[HttpGet]
[Route("query/{queryName}")]
public async Task<IActionResult> Call(string queryName, CancellationToken cancellationToken)
{
  await Task.Delay(5_000, cancellationToken);
  ...
}

如标题所述,我无法在浏览器端启动刷新时让 cancellationToken 触发 TaskCanceledException,而初始请求仍在处理中(Chrome devtools 将这些事件显示为已取消的请求)。我让它工作的唯一方法是在 Visual Studio 的调试设置中选择 "Project"(见下面的屏幕截图),我猜这会使整个应用程序 运行 仅在 Kestrel 中 -前面没有任何反向代理。

我遇到了各种 post,声称此问题将通过 ASP.NET Core 2.2 解决,其中 in-process 托管应与 CancellationToken 结合使用。所以我更新了我所有的 nuget 包,但不幸的是没有效果,错误仍然存​​在。是的,我在本地使用 IIS Express 进行调试,我不确定这与常规 IIS 设置究竟有何不同,但我也在 Azure 上 运行ning 这个应用程序,整个过程看起来就像是运行ning in-process,因为只有一个进程运行ning(见下面的截图)。

这是我安装的 AspNetCore 软件包的 csproj 的摘录:

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net461</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.13.1" />
    <PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Server.IIS" Version="2.2.6" />
    <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.2.0" />
    <PackageReference Include="System.Net.Http" Version="4.3.4" />
  </ItemGroup>
</Project>

我也尝试过 Program.cs,因为我怀疑这可能是另一个潜在的错误来源。我尝试使用 UseIIS() 扩展方法仅强制执行 in-process 托管,但对 CancellationToken:

也没有明显影响
public class Program
{
    public static void Main(string[] args)
    {
        var host = WebHost.CreateDefaultBuilder(args)
            //.UseKestrel()
            .UseIIS()
            .UseContentRoot(Directory.GetCurrentDirectory())
            //.UseIISIntegration()
            .UseStartup<Startup>()
            .UseApplicationInsights()
            .Build();

        host.Run();
    }
}

我的问题:

  1. CancellationToken 是否仅适用于 netcoreapp2.x(或更高版本)作为目标框架?
  2. 这是配置问题吗(Program.cs、Startup.cs、csproj 等)?
  3. 我可以 运行 在 Windows 上的 Azure Web 应用服务上仅使用 Kestrel 时使用此应用程序吗?如果是,我该如何配置?
  4. 还有什么我可能遗漏的吗?

长话短说:原来 Azure 应用服务使用的是 7 级负载均衡器,它不会将连接关闭事件转发到 Web 应用程序。因此,无论您是在 IIS 上使用 Kestrel 还是进程内托管的 Web 应用程序,您的应用程序都不会收到通知。

显而易见的解决方案是在应用程序级别自行处理此类事件。通过设置 KeepAliveInterval (WebSockets) 或使用 SignalR 直接订阅连接关闭事件。