почему мой статический объект создается несколько раз в моем коде asp.net?

Я думаю, что статический объект используется в нескольких потоках. Однако у меня возникла проблема с высокой загрузкой процессора на одном из моих сайтов, поэтому я сделал дамп windbg и очень удивился, я увидел следующее:

введите описание изображения здесь

Мы видим, что существует 10 экземпляров класса ConnectionMultiplexer. Но мой код создает 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);
    }

person daxu    schedule 28.09.2017    source источник
comment
Что касается вашего первого предложения: любой объект находится в куче, и куча доступна любому потоку. Так что тот факт, что он статичен, не имеет значения.   -  person Thomas Weller    schedule 28.09.2017


Ответы (1)


ConnectionMultiplexer на самом деле является свойством только для чтения (get), использующим новый короткий синтаксис C # 7 =>, который возвращает LazyConnection.Value каждый раз, когда вы обращаетесь к нему.

Затем вы используете LazyThreadSafetyMode.PublicationOnly, который определяется как это в MSDN (https://msdn.microsoft.com/en-us/library/system.threading.lazythreadsafetymode(v=vs.110).aspx)

Когда несколько потоков пытаются инициализировать Lazy-экземпляр одновременно, всем потокам разрешается запускать метод инициализации (или конструктор по умолчанию, если метод инициализации отсутствует). Первый поток, завершивший инициализацию, устанавливает значение экземпляра Lazy. Это значение возвращается любым другим потокам, которые одновременно выполняли метод инициализации, если только метод инициализации не вызывает исключения в этих потоках. Любые экземпляры T, созданные конкурирующими потоками, отбрасываются. Если метод инициализации вызывает исключение в каком-либо потоке, исключение распространяется из свойства Lazy.Value в этом потоке. Исключение не кэшируется. Значение свойства IsValueCreated остается ложным, и последующие вызовы свойства Value либо потоком, в котором было создано исключение, либо другими потоками, вызывают повторный запуск метода инициализации. Если метод инициализации рекурсивно обращается к свойству Value экземпляра Lazy, исключение не создается.

Это означает, что если несколько потоков попытаются получить к нему доступ в одно и то же время, каждый из них создаст свой собственный экземпляр, хотя в конечном итоге вы будете использовать первый, созданный независимо от потока (но экземпляры все еще существуют).

На самом деле вам нужно LazyThreadSafetyMode.ExecutionAndPublication, но это может привести к тупикам.

Если вам не нужно быть ленивым, вы можете использовать одну из реализаций одноэлементного шаблона, предложенную Джоном Скитом в его книге C # In Depth.

Вы можете найти их здесь, http://csharpindepth.com/Articles/General/Singleton.aspx

person Mihail Shishkov    schedule 28.09.2017