Ninject InThreadScope 绑定

发布于 2024-10-09 06:54:37 字数 900 浏览 8 评论 0原文

我有一个 Windows 服务,其中包含一个文件观察器,该观察器在文件到达时引发事件。当引发事件时,我将使用 Ninject 创建业务层对象,这些对象内部有对实体框架上下文的引用,该上下文也通过 Ninject 注入。在我的 Web 应用程序中,我始终使用 InRequestScope 作为上下文,这样在一个请求中,所有业务层对象都使用相同的实体框架上下文。在我当前的 Windows 服务场景中,将实体框架上下文绑定切换到 InThreadScope 绑定是否足够?

理论上,当服务中的事件处理程序触发时,它会在某个线程下执行,那么如果另一个文件同时到达,它将在不同的线程下执行。因此,这两个事件不会共享实体框架上下文,本质上就像网络上的两个不同的 http 请求一样。

让我困扰的一件事是这些线程作用域对象的销毁,当您查看 Ninject wiki 时:

.InThreadScope() - 每个线程都会创建该类型的一个实例。
.InRequestScope() - 每个 Web 请求都会创建一个该类型的实例,并在请求结束时销毁。

基于此,我了解到当请求结束时(或之后的某个时刻),InRequestScope 对象将被销毁(收集垃圾?)。然而,这并没有说明 InThreadScope 对象是如何被销毁的。回到我的示例,当文件观察器事件处理程序方法完成时,线程消失(返回到线程池?)注入的 InThreadScope-d 对象会发生什么?

编辑: 现在很清楚的一件事是,当使用 InThreadScope() 时,当文件监视程序的处理程序退出时,它不会销毁您的对象。我能够通过在文件夹中删除许多文件来重现这一点,最终我得到了相同的线程 id,这导致了与以前完全相同的实体框架上下文,所以这对于我的应用程序来说绝对是不够的。在这种情况下,5 分钟后传入的文件可能使用之前分配给同一线程的过时上下文。

I have a Windows service that contains a file watcher that raises events when a file arrives. When an event is raised I will be using Ninject to create business layer objects that inside of them have a reference to an Entity Framework context which is also injected via Ninject. In my web applications I always used InRequestScope for the context, that way within one request all business layer objects work with the same Entity Framework context. In my current Windows service scenario, would it be sufficient to switch the Entity Framework context binding to a InThreadScope binding?

In theory when an event handler in the service triggers it's executed under some thread, then if another file arrives simultaneously it will be executing under a different thread. Therefore both events will not be sharing an Entity Framework context, in essence just like two different http requests on the web.

One thing that bothers me is the destruction of these thread scoped objects, when you look at the Ninject wiki:

.InThreadScope() - One instance of the type will be created per thread.
.InRequestScope() - One instance of the type will be created per web request, and will be destroyed when the request ends.

Based on this I understand that InRequestScope objects will be destroyed (garbage collected?) when (or at some point after) the request ends. This says nothing however on how InThreadScope objects are destroyed. To get back to my example, when the file watcher event handler method is completed, the thread goes away (back to the thread pool?) what happens to the InThreadScope-d objects that were injected?

EDIT:
One thing is clear now, that when using InThreadScope() it will not destroy your object when the handler for the filewatcher exits. I was able to reproduce this by dropping many files in the folder and eventually I got the same thread id which resulted in the same exact Entity Framework context as before, so it's definitely not sufficient for my applications. In this case a file that came in 5 minutes later could be using a stale context that was assigned to the same thread before.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心的憧憬 2024-10-16 06:54:37

线程静态的对象可能会存在很长时间,这意味着ObjectContext有时会变得陈旧并使用旧的(缓存的)值,这将导致难以-找到错误。

我通常会创建一个与创建数据库事务具有相同作用域的 ObjectContext (我什至经常将 ObjectContext 包装在数据库事务中,然后将它们依次处理)。一个(Web)请求可能有多个数据库事务,但通常只有一个执行业务逻辑的“业务事务”。可以启动其他事务作为日志记录(在业务事务之前、之后,有时在业务事务期间)。当您为完整请求重复使用 ObjectContext 时,您可能会陷入混乱,因为当业务事务失败时,ObjectContext 可能处于无效状态,这可能会导致对重用相同ObjectContext的操作(例如日志记录)的影响。

对于 Windows 服务,我认为文件观察器引发的每个事件都可能触发新的业务事务。在这种情况下,我将为每个事件创建一个新的ObjectContext

长话短说,我不会注入一个由 IoC 框架管理生命周期的 ObjectContext。我将注入一个工厂,允许您的代码创建一个新的 ObjectContext 并处置它。我刚刚回答了我们几个人的另一个问题。查看我在该答案中提出的解决方案。

祝你好运。

Objects that are thread-static could possibly live for a very long time, which means that at some time that ObjectContext will get stale and work with old (cached) values, which will result in hard-to-find bugs.

I normally create an ObjectContext with the same scope as I create a database transaction (I often even wrap a ObjectContext in a database transaction and dispose them right after each other). One (web) request could possibly have multiple database transactions, but will usually have one 'business transaction', which executes the business logic. Other transactions could be started for things as logging (before, after, and sometimes during the business transaction). When you reuse the ObjectContext for the complete request you could end up with a mess, because when a business transaction fails, the ObjectContext could be in an invalid state, which might have effect on operations (such as logging) that reuse that same ObjectContext.

With your Windows Service, I think every event raised by the file watcher possibly triggers a new business transaction. In that case I would create a new ObjectContext per event.

Long story short, I would not inject an ObjectContext that has a lifetime that is managed by your IoC framework. I would inject a factory that allows your code to create a new ObjectContext and dispose it. I just answered another question about this a few ours back. Look at the solution I propose in that answer.

Good luck.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文