Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 独生子女和种族条件_C#_Multithreading_Ninject - Fatal编程技术网

C# 独生子女和种族条件

C# 独生子女和种族条件,c#,multithreading,ninject,C#,Multithreading,Ninject,关于这个问题: 但我将单独提出这个问题,因为我认为这可能是Ninject的一个问题,我不想混淆原来的问题,以防我错了 我的问题是,我有一个web api项目,它使用Ninject来管理依赖项注入,大多数情况下,它工作正常。问题是,如果在启动应用程序后立即发出多个请求,有时它们会以某种非常奇怪的方式失败,出现NullReferenceExceptions,对于看起来不为null的对象,这些异常根本不应该存在。我想知道Ninject使用InSingletonScope时是否会出现问题,不是真的给我

关于这个问题:

但我将单独提出这个问题,因为我认为这可能是Ninject的一个问题,我不想混淆原来的问题,以防我错了

我的问题是,我有一个web api项目,它使用Ninject来管理依赖项注入,大多数情况下,它工作正常。问题是,如果在启动应用程序后立即发出多个请求,有时它们会以某种非常奇怪的方式失败,出现
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;