【发布时间】:2014-09-17 08:01:56
【问题描述】:
我的问题与此有点相关:WebApi equivalent for HttpContext.Items with Dependency Injection。
我们想使用 Ninject 在 WebApi 区域中使用 HttpContext.Current 注入一个类。
我担心的是,这可能非常危险,因为在 WebApi 中(一切?)都是异步的。
如果我在这些方面有错误,请纠正我,这是我目前调查的内容:
-
HttpContext.Current 通过 Thread 获取当前上下文(我直接查看了实现)。
-
在异步任务中使用 HttpContext.Current 是不可能的,因为它可以在另一个线程上运行。
-
WebApi 使用 IHttpController 和方法
Task<HttpResponseMessage> ExecuteAsync=> 每个请求都是异步的 => 你不能在 action 方法中使用 HttpContext.Current。它甚至可能发生,更多的请求在同一个线程上执行。 -
为了在构造函数中注入东西来创建控制器
IHttpControllerActivator与 sync 方法IHttpController Create一起使用。这就是 ninject 创建 Controller 及其所有依赖项的地方。
-
如果我在所有这 4 点上都正确,那么在操作方法内部或下面的任何层中使用
HttpContext.Current是非常危险的,并且可能会产生意想不到的结果。我在 StackOverflow 上看到了很多公认的答案,这些答案正是表明了这一点。在我看来,这可以工作一段时间,但会在负载下失败。 -
但是当使用 DI 创建一个 Controller 及其依赖项时,没关系,因为它运行在一个单独的线程上。 我可以从构造函数中的 HttpContext 中获取一个值,这样会安全吗?。我想知道每个控制器是否针对每个请求都在单个线程上创建,因为这可能会在负载过重的情况下导致问题,其中 IIS 的所有线程都可能被消耗。
只是为了解释一下我为什么要注入 HttpContext 的东西:
- 一种解决方案是在控制器操作方法中获取请求,并将所需的值作为参数传递给所有层,直到它在代码深处使用。
- 我们想要的解决方案:之间的所有层都不受此影响,我们可以在代码深处的某处使用注入的请求(例如,在某些依赖于 URL 的
ConfigurationProvider中)
如果我完全错误或我的建议是正确的,请给我您的意见,因为这个主题似乎很复杂。
【问题讨论】:
-
这是一个非常有趣的问题。但是,据我所知,如果代码没有明确地将工作推迟到另一个线程,那么东西仍然会在同一个线程上执行。对于异步任务也是如此。虽然它不会阻塞调用者线程,但它仍然会在调用者线程上执行。但我不是 100% 确定.. 你应该试一试;-)
-
这正是问题所在 - await 你大部分时间都停留在同一个线程上,但你不能确定这一点。这就是为什么 IMO 每个人都认为它有效,但在某些情况下会中断。使用 Task.Run,可以肯定的是,它是另一个线程。
-
为什么你认为你不能确定呢?比“同步”方法更重要?同步方法也可以执行
Task.Run(..)或者它可以生成一个新线程并在该线程中尝试注入 HttpContext 等等。那么有什么区别? -
当你做
Task.Run时,你自己做,你知道会发生什么,这对我来说没问题。我担心的是,由于 webapi 中的 action-method 是由框架异步运行的,所以它总是被认为是异步的,并且存在所有缺陷。我认为,它甚至可能发生,两个请求在同一个线程上运行(我认为这是等待/异步的目的)=> HttpContext.Current 将返回错误的值。实际上这个问题已经打击了我一次,通过登录 WebApi 意识到 log4net LogicalThreadContext.Properties 不起作用,但在 MVC 中它们确实起作用。 -
回答你的问题,为什么我认为它不确定它是否在同一个线程上运行? - 我在互联网上阅读了很多文章,似乎社区对此不太确定,但我感觉 SyncronizationContext 将根据当前情况决定是否启动新线程,但实际上这种情况很少发生。 (仍然不确定 100% 关于这一点,因为互联网上有许多不同的意见)
标签: multithreading asynchronous asp.net-web-api ninject httpcontext