在新任务中使用的依赖注入服务

时间:2017-07-18 09:23:22

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

我正在使用依赖注入来在需要时访问我的服务,但我现在想要创建一个并发任务,但这会导致由于依赖注入对象及其生命周期引起的问题。

我读过这篇文章(标题:防止多线程):Link 从那以后,我认为这是不可能的。

我的目标是让客户端发送一个请求来开始一个可能需要比客户端的连接超时更长的工作,因此我希望有一个端点启动任务并返回任务是否成功的状态开始。

问题在于,因为数据库上下文和其他服务是在请求的线程内的控制器上创建的,所以当您将该对象传递给新任务并结束旧任务时,对象将因为他们是在所说的帖子上创建的。

我知道对于数据库上下文,您可以注入数据库工厂接口并创建一个新实例,但这对我的非数据库对象没有帮助。 (我还读到创建自己的服务实例会破坏依赖注入点。)

有没有办法可以在新线程/任务上创建注入依赖项的新实例,或者完全避免这个问题?感谢。

1 个答案:

答案 0 :(得分:3)

  

创建并发任务,但这会导致依赖注入对象及其生命周期引起的问题。

每次分离后台线程或可能并行运行在不同线程上的任务时,在该操作期间您需要做的第一件事就是从容器中请求您要使用的服务。这样,容器可以根据他们的生活方式确定需要构建哪些对象。将依赖关系从线程移动到另一个(可能并行运行)线程是一种罪过。

查看following information以了解如何在多线程应用程序中使用DI。这些信息是在考虑特定DI容器的情况下编写的,但大多数信息一般适用于DI。

在您的情况下,您希望将请求的数据转发到能够启动新线程的类,创建新范围,从该范围解析实际处理程序并调用它。您可以在this answer中看到非常相似的内容。

  

还是完全避免这个问题?

您应该只关闭后台线程上的操作,以防您不关心它们是成功还是失败。但是,在大多数业务事务中,当操作失败时,您希望通知用户有关此信息以告知用户必须重试,或者您希望代表他自动重试该操作。如果你只是在后台线程上分离操作,这很难实现。

更好的解决方案是使用持久排队机制。这可以是数据库队列或消息队列。这种技术可确保操作不会丢失,并且通常具有内置的重试机制。看看MassTransit或NServiceBus,例如在RabbitMq,MSMQ或SQL Server之上运行。