【问题标题】:AddScoped dependency with a CancellationToke带有 CancellationToke 的 AddScoped 依赖项
【发布时间】:2021-01-20 02:44:18
【问题描述】:

我有一个针对每个 REST API 请求的 .NET 核心依赖项。它通过调用AddScoped 添加到Startup.ConfigureServices

我想为此添加取消支持。如果我将CancellationToken cancellationToken 添加到任何控制器操作的参数中,我可以获得一个令牌,如果客户端请求是,则该令牌会被取消。然后我可以将该令牌传递给我的依赖项上的所有方法。

但是,依赖项的范围是请求,因此通过操作将令牌向下传递给方法是不必要的 - 我可以以某种方式将 CancellationToken 添加到范围依赖项中吗?

【问题讨论】:

  • @Métoule 可能,尽管这个问题似乎是在询问一般情况(即瞬态和静态范围),我认为这可能意味着它无法完成。我特别要求更窄的AddScoped 案例 - 我注入的依赖项存在于与取消令牌适用的完全相同的范围内。
  • 没有必要。取消令牌用于提前取消正在进行的操作(即长时间运行的循环))并且独立于范围,因此尽快停止请求并释放请求可能仍然有用。请求可能因多种原因被取消,例如连接丢失、用户不小心在浏览器中连续两次单击链接或在页面加载时按 ESC
  • @Tseng 是的,并且可能存在需要为特定范围传递取消令牌的用例。但是,这里的连接丢失、用户重复或中止请求都在同一个范围内——这些与 .NET 没有不同的标记,它们都是 HTTP 取消,在操作上看起来是一样的。范围是相同的。

标签: c# asp.net-core .net-core dependency-injection request-cancelling


【解决方案1】:

我可以以某种方式将 CancellationToken 添加到作用域依赖项中吗?

嗯,技术上是的。即通过注入 IHttpAccessor 并访问 HttpContext.RequestAborted 属性,如果已定义,您通常会传递给控制器​​操作。

但实际上不鼓励使用动作参数重载,因为在每个控制器动作中,您都可以通过HttpContext.RequestAborted 访问取消令牌,并且在控制器动作中使用它会使令牌公开,即在创建 Swagger 方案时(至少是2017 年的案例),其中使用 HttpContext 本身并没有将其暴露给公众。

唯一的例外似乎是,当使用不继承自 ControllerControllerBase 并且未将 IHttpAccessor 注入此控制器的“Poco 控制器”时。

但是将取消令牌注入任意服务是有问题的,因为您会严重依赖 Web 框架 (IHttpAccessor/HttpContext)。

最好和最干净的方法是在您的方法上保留CancellationToken 参数,该参数可以以有意义的方式取消并使令牌可选,因此您只能在您有请求的情况下传递参数或以下情况可以取消

public Task<Result> ProcessSomething(string param1, CancellationToken cancellationToken = default)
{
}

【讨论】:

  • 所以我应该在操作参数中使用var cancellationToken = this.HttpContext.RequestAborted; 而不是取消标记,而在我的Startup.ConfigureServices 中应该使用services.AddScoped&lt;ICancelable&gt;(provider =&gt; new CancelableImpl(provider.GetService&lt;IHttpContextAccessor&gt;()?.HttpContext?.RequestAborted ?? default)?
  • @Keith:不。实际上,最好的方法是将取消标记作为可以取消的操作的方法参数,因为在某些时候,您的任何服务都会在某个时间点或另一个点从控制器调用。出于明显的原因,那些不需要的也不需要 http 请求取消令牌
猜你喜欢
  • 2021-12-11
  • 2019-12-19
  • 2014-07-17
  • 2011-05-26
  • 2011-03-09
  • 2017-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多