C# 独生子女和种族条件
关于这个问题: 但我将单独提出这个问题,因为我认为这可能是Ninject的一个问题,我不想混淆原来的问题,以防我错了 我的问题是,我有一个web api项目,它使用Ninject来管理依赖项注入,大多数情况下,它工作正常。问题是,如果在启动应用程序后立即发出多个请求,有时它们会以某种非常奇怪的方式失败,出现C# 独生子女和种族条件,c#,multithreading,ninject,C#,Multithreading,Ninject,关于这个问题: 但我将单独提出这个问题,因为我认为这可能是Ninject的一个问题,我不想混淆原来的问题,以防我错了 我的问题是,我有一个web api项目,它使用Ninject来管理依赖项注入,大多数情况下,它工作正常。问题是,如果在启动应用程序后立即发出多个请求,有时它们会以某种非常奇怪的方式失败,出现NullReferenceExceptions,对于看起来不为null的对象,这些异常根本不应该存在。我想知道Ninject使用InSingletonScope时是否会出现问题,不是真的给我
NullReferenceExceptions
,对于看起来不为null的对象,这些异常根本不应该存在。我想知道Ninject使用InSingletonScope
时是否会出现问题,不是真的给我一个单例,而是有时会给我一些尚未完成初始化的东西(但可能是在我在调试器中查看它时初始化的)。这可能吗?还是我完全找错了方向
我使用Nuget软件包和一些web资源设置了Ninject(很抱歉,我似乎没有确切链接到哪些资源),我认为我做得对。我的项目中有对Ninject
和Ninject.web.Common
的引用。在NinjectWebCommon.cs
中,我有这个用于注册一系列服务(我排除了其中的大部分,以孤立给我带来麻烦的一个):
我尝试了几种不同的方法来绑定它(第二种方法是在回答这个问题时提出的:),但当我的API控制器在MyFinderService
上调用此方法时,似乎还是有点不对劲:
public MyClassBase GetThing(Guid id)
{
if (cache.ContainsKey(id))
{
return cache[id];
}
else
{
var type = typeof(MyClassBase).Assembly.GetTypes().FirstOrDefault
(
t => t.IsClass &&
t.Namespace == typeof(MyClassBase).Namespace + ".Foo" &&
t.IsSubclassOf(typeof(MyClassBase)) &&
(t.GetCustomAttribute<MyIdAttribute>()).GUID == id
);
if (type != null)
{
System.Diagnostics.Debug.WriteLine(string.Format("Cache null: {0}",cache == null));
var param = (MyClassBase)Activator.CreateInstance(type, userService);
cache[id] = param;
return param;
}
return null;
}
}
即使在调试器缓存中,id
和param
似乎都有值
我的假设是,当我将某个东西注册为单例时,Ninject将处理所有细节,确保它确实是单例,并在惰性初始化期间锁定访问,以确保它不会创建单独的单例,但也许我错了
因此,如何在web api项目的上下文中安全地创建和注册类的单个实例,该项目可能会收到来自不同线程的多个请求。如果您使用的是Ninject.web.WebApi.WebHost
,InSingletonScope将以线程安全的方式为您提供单个实例
但不幸的是,有许多博客文章和stackoverflow答案显示,使用ActivationBlock的DependencyResolver实现没有正确实现,即使它们注册为Singleton,也会在请求范围内为您提供一个对象
Ninject不做的是确保返回的对象本身是线程安全的。您的情况似乎就是这样。字典
的内部结构不是线程安全的。只允许一个线程同时修改字典。您应该切换到ConcurrentDictionary
当然,它是一个ingleton,但它是线程安全的吗?它似乎不是。如果您可以让多个线程同时访问它,那么最好使用ConcurrentDictionary
。感谢Remo,切换到ConcurrentDictionary
似乎是解决问题的方法,并且最好确认Ninject是线程安全的(假设您返回的东西本身是线程安全的)。我认为它一定是线程安全的,但是这个特定的bug让我发疯了!
public MyFinderService(IUserService service)
{
cache = new Dictionary<Guid, MyClassBase>();
userService = service;
}
public MyClassBase GetThing(Guid id)
{
if (cache.ContainsKey(id))
{
return cache[id];
}
else
{
var type = typeof(MyClassBase).Assembly.GetTypes().FirstOrDefault
(
t => t.IsClass &&
t.Namespace == typeof(MyClassBase).Namespace + ".Foo" &&
t.IsSubclassOf(typeof(MyClassBase)) &&
(t.GetCustomAttribute<MyIdAttribute>()).GUID == id
);
if (type != null)
{
System.Diagnostics.Debug.WriteLine(string.Format("Cache null: {0}",cache == null));
var param = (MyClassBase)Activator.CreateInstance(type, userService);
cache[id] = param;
return param;
}
return null;
}
}
cache[id] = param;