Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.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代码中多次创建静态对象?_C#_Windbg_Stackexchange.redis - Fatal编程技术网

C# 为什么在asp.net代码中多次创建静态对象?

C# 为什么在asp.net代码中多次创建静态对象?,c#,windbg,stackexchange.redis,C#,Windbg,Stackexchange.redis,我认为静态对象是跨多个线程共享的。然而,我的一个站点出现了高CPU问题,因此我进行了windbg转储,非常惊讶地发现: 我们可以看到一个名为ConnectionMultiplexer的类有10个实例。但我的代码将ConnectionMultiplexer创建为静态对象。这意味着只能为所有线程创建一个实例。那么windbg为什么会显示多个实例呢 这是我创建redis连接的代码 public static class CacheConnection { private st

我认为静态对象是跨多个线程共享的。然而,我的一个站点出现了高CPU问题,因此我进行了windbg转储,非常惊讶地发现:

我们可以看到一个名为ConnectionMultiplexer的类有10个实例。但我的代码将ConnectionMultiplexer创建为静态对象。这意味着只能为所有线程创建一个实例。那么windbg为什么会显示多个实例呢

这是我创建redis连接的代码

public static class CacheConnection
    {
        private static StackExchangeRedisCacheClient _newconnectionDb;

        public static StackExchangeRedisCacheClient NewConnectionDb
            => _newconnectionDb ?? (_newconnectionDb = NewRedisConnection());

        private static IDatabase _connectionDb;

        public static IDatabase ConnectionDb => _connectionDb ?? (_connectionDb = RedisConnection());

        private static StackExchangeRedisCacheClient NewRedisConnection()
        {
            var serializer = new NewtonsoftSerializer();
            return new StackExchangeRedisCacheClient(Connection, serializer);
        }

        private static IDatabase RedisConnection()
        {
            var cacheDatabase = Connection.GetDatabase();
            return cacheDatabase;
        }

        public static ConnectionMultiplexer Connection => LazyConnection.Value;

        private static readonly Lazy<ConnectionMultiplexer> LazyConnection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(
            System.Configuration.ConfigurationManager.AppSettings["CacheConnectionString"]), LazyThreadSafetyMode.PublicationOnly);
    }
公共静态类缓存连接
{
私有静态StackExchangeDiscacheClient\u newconnectionDb;
公共静态堆栈ExchangeDiscacheClient新连接DB
=>_newconnectionDb??(_newconnectionDb=NewRedisConnection());
私有静态IDatabase_connectionDb;
公共静态IDatabase ConnectionDb=>_ConnectionDb??(_ConnectionDb=RedisConnection());
私有静态StackExchangeDiscacheClient NewRedisConnection()
{
var serializer=newnewtonsoftserializer();
返回新的StackExchangeDiscacheClient(连接、序列化程序);
}
私有静态IDatabase重新连接()
{
var cacheDatabase=Connection.GetDatabase();
返回缓存数据库;
}
公共静态连接多路复用器连接=>LazyConnection.Value;
private static readonly Lazy Lazy connection=new Lazy(()=>ConnectionMultiplexer.Connect(
System.Configuration.ConfigurationManager.AppSettings[“CacheConnectionString]”),LazyThreadSafetyMode.PublicationOnly);
}

ConnectionMultiplexer
实际上是一个只读(get)属性,使用新的C#7短语法=>每次访问时返回
LazyConnection.Value

然后使用
LazyThreadSafetyMode.PublicationOnly
,它在MSDN()中定义为

当多个线程尝试初始化惰性实例时 同时,允许所有线程运行初始化 方法(或默认构造函数,如果没有初始化 方法)。完成初始化的第一个线程设置 懒惰的实例。该值将返回给执行以下操作的任何其他线程 正在同时运行初始化方法,除非 初始化方法在这些线程上抛出异常。任何 由竞争线程创建的T实例包括 丢弃的。如果初始化方法在任何 线程,异常将从Lazy.Value属性传播出去 在那条线上。该异常未缓存。价值 IsValueCreated属性保持为false,随后调用 值属性,由引发异常的线程或 通过其他线程,使初始化方法再次运行。如果 初始化方法递归地访问 惰性实例,不会引发任何异常

这意味着,如果多个线程试图同时访问它,它们将各自创建自己的实例,尽管不管线程是什么,最终都会使用创建的第一个实例(但实例仍然存在)

您实际需要的是
LazyThreadSafetyMode.ExecutionAndPublication
但这可能会导致僵局

如果你不需要这样做,你可以使用Jon Skeet在他的书C#Depth中建议的一种单例模式实现


关于第一句话,你可以在这里找到它们:堆上有任何对象,堆对任何线程都可用。因此,它是静态的这一事实与此无关。