为什么 NamedScopes 从终结器调用 dispose 方法?
Why NamedScopes invoke dispose methods from finalizer?
我注意到当我在 Ninject 命名范围内使用 IDisposable
对象时,我的 Dispose
方法是从终结器调用的。但我的对象或其中的一些引用可能在那时已经完成。
我错过了什么吗?这是正确的行为还是错误?
堆栈跟踪:
в NInjectNamedScopes.User.ChatService.Dispose()
в Ninject.Activation.Strategies.DisposableStrategy.<Deactivate>b__0(IDisposable x)
в Ninject.Activation.InstanceReference.IfInstanceIs[T](Action`1 action)
в Ninject.Activation.Pipeline.<>c__DisplayClass6.<Deactivate>b__4(IActivationStrategy s)
в Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map[T](IEnumerable`1 series, Action`1 action)
в Ninject.Activation.Caching.Cache.Forget(CacheEntry entry)
в Ninject.Activation.Caching.Cache.Forget(IEnumerable`1 cacheEntries)
в Ninject.Activation.Caching.Cache.Clear(Object scope)
в Ninject.Extensions.NamedScope.DisposeNotifyingObject.Dispose(Boolean disposing)
в Ninject.Infrastructure.Disposal.DisposableObject.Finalize()
因为 ninject 仍然引用了您的 IDisposable
,所以您的 IDisposable
应该不可能已经完成。但是,在您的情况下, Dispose
方法是从终结器调用的,这似乎很奇怪。你能提供堆栈跟踪吗?
命名范围行为
默认情况下 InNamedScope
,ninject 保留 WeekReference
到 DefinesNamedScope
(root) 并定期检查它是否仍然存在。一旦它被检测为垃圾收集,该范围的 InNamedScope
-对象将被释放(Ninject 保持对这些的强烈引用)。
要确保 InNamedScope
-d 对象在范围根对象之后立即处理,请将 INotifyWhenDisposed
添加到范围根。
- 一般来说,从终结器访问其他托管对象是一种非常糟糕的做法。
- 我在
NamedScopes
个扩展的源代码中发现了一些其他与性能相关的问题。
所以是的,这是一个错误,我建议大家根本不要使用 NamedScopes 扩展,直到它被修复。我个人进行了一些性能测试并选择了另一个 IoC 容器 AutoFac,它的工作速度提高了一个数量级。
我注意到当我在 Ninject 命名范围内使用 IDisposable
对象时,我的 Dispose
方法是从终结器调用的。但我的对象或其中的一些引用可能在那时已经完成。
我错过了什么吗?这是正确的行为还是错误?
堆栈跟踪:
в NInjectNamedScopes.User.ChatService.Dispose()
в Ninject.Activation.Strategies.DisposableStrategy.<Deactivate>b__0(IDisposable x)
в Ninject.Activation.InstanceReference.IfInstanceIs[T](Action`1 action)
в Ninject.Activation.Pipeline.<>c__DisplayClass6.<Deactivate>b__4(IActivationStrategy s)
в Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map[T](IEnumerable`1 series, Action`1 action)
в Ninject.Activation.Caching.Cache.Forget(CacheEntry entry)
в Ninject.Activation.Caching.Cache.Forget(IEnumerable`1 cacheEntries)
в Ninject.Activation.Caching.Cache.Clear(Object scope)
в Ninject.Extensions.NamedScope.DisposeNotifyingObject.Dispose(Boolean disposing)
в Ninject.Infrastructure.Disposal.DisposableObject.Finalize()
因为 ninject 仍然引用了您的 IDisposable
,所以您的 IDisposable
应该不可能已经完成。但是,在您的情况下, Dispose
方法是从终结器调用的,这似乎很奇怪。你能提供堆栈跟踪吗?
命名范围行为
默认情况下 InNamedScope
,ninject 保留 WeekReference
到 DefinesNamedScope
(root) 并定期检查它是否仍然存在。一旦它被检测为垃圾收集,该范围的 InNamedScope
-对象将被释放(Ninject 保持对这些的强烈引用)。
要确保 InNamedScope
-d 对象在范围根对象之后立即处理,请将 INotifyWhenDisposed
添加到范围根。
- 一般来说,从终结器访问其他托管对象是一种非常糟糕的做法。
- 我在
NamedScopes
个扩展的源代码中发现了一些其他与性能相关的问题。
所以是的,这是一个错误,我建议大家根本不要使用 NamedScopes 扩展,直到它被修复。我个人进行了一些性能测试并选择了另一个 IoC 容器 AutoFac,它的工作速度提高了一个数量级。