Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.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/7/wcf/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#ASP.NET MVC 3单例构造函数调用两次_C#_Wcf_Asp.net Mvc 3_Singleton - Fatal编程技术网

C#ASP.NET MVC 3单例构造函数调用两次

C#ASP.NET MVC 3单例构造函数调用两次,c#,wcf,asp.net-mvc-3,singleton,C#,Wcf,Asp.net Mvc 3,Singleton,我有一个由三个项目组成的项目 WCF服务 Asp.NETMVC3应用程序 类库 类库中的一个是我的单件,我这样做的 public sealed class Singleton { public static Singleton Instance { get; set; } private Singleton() { } public static Singleton Instance { get {

我有一个由三个项目组成的项目

  • WCF服务
  • Asp.NETMVC3应用程序
  • 类库
  • 类库中的一个是我的单件,我这样做的

    public sealed class Singleton
    {
        public static Singleton Instance { get; set; }
    
        private Singleton()
        {
    
        }
    
        public static Singleton Instance
        {
            get
            {
                if (Instance == null)
                    Instance = new Singleton();
                return Instance;
            }
        }       
    }
    
    问题是,我在构造函数中放入了一个
    Debug.WriteLine
    ,它被调用了两次
    我尝试使用MVC3应用程序和WCF服务中的单例,但它们生成不同的实例。为什么?


    编辑:我之前试过一个安全的单人游戏。这没什么区别。

    我没有使用WCF的经验,但也许您应该实现线程安全的单例,请参阅:

    我想您的实现不是线程安全的。查看文章:

    这里有一个线程安全的例子:(有许多其他方法可以做到这一点,更复杂和更安全,这只是一个参考…)


    如果WCF服务作为一个单独的应用程序运行,它将拥有自己的单例实例,因为这两个应用程序不共享内存


    WCF服务是否在与MVC应用程序不同的IP地址/端口号上运行?

    这里可能会发生一些事情

    最可能的情况是MVC应用程序和WCF服务运行在不同的AppDomain中。如果是这种情况,代码将不可能“共享”同一实例

    另一个不太可能的原因是,因为代码不是线程安全的,所以创建了多个实例。如果单例构造函数需要很长时间才能返回,那么这可能就是问题所在。由于您使用的是MVC3,因此我假设.Net 4是您的朋友:

    private static readonly Lazy<Singleton> _singleton = new Lazy<Singleton>(() => new Singleton());
    public static Singleton Instance { get { return _singleton.Value; } }
    
    private static readonly Lazy _singleton=new Lazy(()=>new singleton());
    公共静态单例实例{get{return}Singleton.Value;}
    
    首先,您发布的确切代码不起作用。它在语法上不正确(大括号不平衡),并且有两个公共Singleton.Instance成员。我假设您的原始代码是这样的:

    public sealed class Singleton
    {
        private static Singleton _instance { get; set; }
    
        private Singleton()
        {
    
        }
    
        public static Singleton Instance
        {
            get
            {
                if (_instance == null)
                    Instance = new Singleton();
                return _instance;
            }
        }       
    }
    
    问题可能与多线程环境有关。也就是说,当一个线程调用
    new Singleton()
    时,另一个线程尝试获取
    Singleton.Instance
    ,该实例反过来调用另一个
    new Singleton()

    您应该在此处使用双重检查锁定:

    public sealed class Singleton
    {
        private static Singleton _instance { get; set; }
    
        private Singleton()
        {
    
        }
    
        public static Singleton Instance
        {
            get
            {
                if (_instance == null)
                    lock (typeof(Singleton))
                        if (_instance == null)
                        {
                            var instance = new Singleton();
                            _instance = instance;
                        }
                return _instance;
            }
        }       
    }
    
    或者,更容易

    public sealed class Singleton
    {
        public static readonly Singleton _instance = new Singleton();
    
        private Singleton()
        {
    
        }
    }
    

    您可以在.NET4.0中使用惰性模式

    public sealed class Singleton
    {
        private static readonly Lazy<Singleton> lazy =
            new Lazy<Singleton>(() => new Singleton());
    
        public static Singleton Instance { get { return lazy.Value; } }
    
        private Singleton()
        {
        }
    } 
    
    公共密封类单例
    {
    私有静态只读惰性=
    新的懒惰(()=>newsingleton());
    公共静态单例实例{get{return lazy.Value;}}
    私人单身人士()
    {
    }
    } 
    


    来源:

    您的代码显然不是线程安全的,但这不应导致构造函数以可复制的方式被调用两次。可能您的WCF服务和ASP.net应用程序位于不同的
    AppDomain
    s中。每个
    AppDomain
    都有自己的静态变量,因此也有自己的单例。这是必要的,因为(大多数)对象不能在
    AppDomain
    s.@Hadas之间共享。这是不正确的。如果还有一个静态构造函数(带有登录代码),您的建议就会发生。但是.Net在请求一个实例之前不会初始化一个实例。顺便说一句:我会避免使用
    MyClass.instance
    singleton而使用IoC singleton@哈达斯你什么意思?你的话毫无意义,那是一篇老文章。新链接:锁定类型是一种糟糕的做法。好吧,我尝试在没有就地静态字段初始值设定项的情况下进行锁定。无论如何,没有理由偏好第一种方式(使用锁,无论是在特殊的SyncRoot对象上还是在类型上)。我认为您的第一个示例也不能保证在EMCA内存模型中是线程安全的您的第二个实例有一个潜在的问题:该实例可以比预期的更早创建,因为它是一个before字段init类。在大多数情况下,这不是问题。@CodeInChaos,您能解释一下为什么第一个示例不是线程安全的吗?有没有可能
    \u instance=instance
    不是原子的?双重锁定需要足够强大的内存模型。我认为EMCA内存模型太弱,而.NET2.0模型足够强大。我尝试过使用tread安全单例,但它产生了相同的结果。那么这是AppDomain的问题吗?@kjelelook再次阅读了关于AppDomains的部分。现在我在构造函数中有一个Debug.WriteLine,我只在mvc 3应用程序中使用单例。还是打了两次电话。一定还有其他的东西。@Kjelelook你在使用
    懒惰的
    类吗?认为它现在可以工作了,没有懒惰的人。谢谢你的帮助,我知道这是AppDomain的东西;)然后您将始终有两个单例实例。每个应用程序一个。双重检查模式+1。然而,我不认为其他任何解决方案会更安全?
    
    public sealed class Singleton
    {
        private static readonly Lazy<Singleton> lazy =
            new Lazy<Singleton>(() => new Singleton());
    
        public static Singleton Instance { get { return lazy.Value; } }
    
        private Singleton()
        {
        }
    }