ASP.NET Core 3框架揭秘之 异步线程无法使用IServic

建站知识 2025-04-16 17:28www.168986.cn长沙网站建设

标题:ASP.NET Core 3中异步线程与IServiceProvider的问题

一、问题的出现

上周五,一位同事向我提出了一个问题,关于ASP.NET Core中的依赖注入框架的使用。具体的问题场景是,在一个ASP.NET Core MVC应用中,尝试在一个异步线程中使用IServiceProvider获取Scoped服务实例时遇到了问题。这个问题不仅关乎依赖注入的正确使用,也涉及到服务实例的生命周期和ASP.NET Core框架内部的运行机制。

二、问题重现

为了更具体地展示这个问题,我们创建了一个简单的ASP.NET Core MVC应用。在程序的入口点,我们启用了对服务范围的验证,并注册了一个Scoped生命周期的服务IFoobar。我们创建了一个HomeController,并在其构造函数中注入了IServiceProvider。

在HomeController的Index方法中,我们使用Task.Run启动了一个异步任务。在这个异步任务中,我们尝试通过注入的IServiceProvider获取IFoobar服务实例。运行应用后,访问该Controller的Index方法,我们发现控制台输出了错误信息。

三、问题的根源

这个问题的根源在于ASP.NET Core的依赖注入框架设计。在ASP.NET Core中,服务实例的生命周期是与请求上下文紧密关联的。对于Scoped生命周期的服务,每个请求都会创建一个新的服务实例,并且在请求结束时,这些实例会被正确地释放。当我们在异步任务中尝试获取Scoped服务实例时,问题就出现了。因为异步任务的执行上下文并不是发起请求的原始上下文,所以ASP.NET Core框架无法正确地为其提供Scoped服务实例。当我们尝试获取IFoobar服务实例时,会抛出异常。

四、解决方案

解决这个问题的一种方法是避免在异步任务中使用IServiceProvider获取Scoped服务实例。我们可以将需要使用的服务作为参数传递给异步任务,或者在异步任务的执行上下文中重新创建服务实例。这样可以确保服务的正确获取和使用。另一种解决方案是调整服务的生命周期,将Scoped服务更改为Singleton或服务实例的生命周期更长。但这需要根据具体的应用场景和需求来决定。

这个问题让我们更深入地理解了ASP.NET Core的依赖注入框架和服务的生命周期。正确地使用依赖注入框架对于构建健壮、可维护的ASP.NET Core应用至关重要。通过理解服务的生命周期和如何在不同的场景下使用服务,我们可以更有效地利用ASP.NET Core的依赖注入框架,构建出更高效、更可靠的应用。二、ApplicationServices与RequestServices的

从展示的错误信息中,我们可以清晰地看到问题源于尝试使用一个已经被Dispose的IServiceProvider来获取服务实例。在ASP.NET Core应用中,服务实例主要是通过代表DI容器的IServiceProvider提供的。这里涉及两种类型的IServiceProvider对象:ApplicationServices和RequestServices。

ApplicationServices与应用的生命周期保持一致,主要在管道构建过程中提供所需的服务实例。而针对每个请求的特定处理过程中所需的服务实例,则由RequestServices提供。每当ASP.NET Core接收到一个请求时,它会使用ApplicationServices创建一个代表服务范围的IServiceScope对象,这个对象实际上是对RequestServices的封装。当请求处理完毕后,服务范围结束,RequestServices被Dispose。

在演示的实例中,注入到HomeController构造函数中的IServiceProvider实际上是RequestServices。由于在某些后台线程中的操作涉及对RequestServices的使用,而在那些操作时当前请求可能已经处理完毕(比如我们人为等待的100毫秒),因此出现了上述异常。

三、如何获取并使用ApplicationServices

既然与请求绑定的RequestServices不可用,我们需要转向使用与应用绑定的ApplicationServices。在ASP.NET Core 3中,IHost接口提供了一个名为Services的属性,正是我们所需要的ApplicationServices。这个属性返回一个IServiceProvider,可以用于获取应用所需的服务。

四、揭开服务实例生命周期的奥秘

在ASP.NET Core 3框架中,我们经常会遇到一个棘手的问题:在异步线程中直接使用IServiceProvider服务实例时,生命周期模式为Scoped的服务实例无法正常运作。这个问题的根源在于我们尝试用一个代表“根容器”的IServiceProvider对象去服务实例。为了解决这个问题,我们需要根据ApplicationServices创建一个“服务范围”,在这个服务范围内提取所需的服务实例。为了确保服务实例能够被正常回收,我们还需要及时终结代表服务范围的IServiceScope对象。正确的编程方式如下:

在HomeController类中,我们通过IHost对象获取ApplicationServices,并在异步任务中创建一个IServiceScope对象。在这个服务范围内,我们可以获取到具有相同生命周期的服务实例。这种方式确保了服务实例的正确使用和及时回收。

五、寻找统一的解决方案

过去,我们为了解决如何获取与当前应用具有相同生命周期的ApplicationServices的问题,选择了注入IHost的方式。在传统的基于IWebHost/IWebHostBuilder的承载方式下,IHost无法直接获取。其实我们真正需要的是利用它创建一个代表服务范围的IServiceScope对象,并在该范围内消费所需的服务实例。由于IServiceScope是通过IServiceScopeFactory创建的,因此我们只需要注入IServiceScopeFactory即可轻松解决问题。

以上所述是长沙网络推广团队为大家介绍的ASP.NET Core 3框架中关于异步线程无法使用IServiceProvider问题的解决方案。希望对大家有所帮助。如有任何疑问,请随时留言,我们会及时回复。感谢大家对狼蚁SEO网站的支持和关注!如果你觉得本文对你有所帮助,欢迎转载并注明出处。谢谢!

(注:在将文章内容渲染到网页或其他媒介时,请确保遵循相关的排版和格式要求,以保持内容的可读性和美观性。)

上一篇:PHP实现连接设备、通讯和发送命令的方法 下一篇:没有了

Copyright © 2016-2025 www.168986.cn 狼蚁网络 版权所有 Power by