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 {
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()
{
}
}